How would I go about defining the following string for the following function?
As of now I get the warning:
C4047: '=' : 'const char' differs in levels of indirection from 'char [4]'
and the error:
C2166: l-value specifies const object.
Both in the third line of the code below:
uint8_t *buffer= (uint8_t *) malloc(sizeof(uint32_t));
const char *stringaling= (const char *) malloc(sizeof(uint32_t));
*stringaling = "fun";
newval = protobuf_writeString (buffer, stringaling);
uint32_t protobuf_writeString(uint8_t *out,const char * str)
{
if (str == NULL)
{
out[0] = 0;
return 1;
}
else
{
size_t len = strlen (str);
size_t rv = uint32_pack (len, out);
memcpy (out + rv, str, len);
return rv + len;
}
}
const char *stringaling= (const char *) malloc(sizeof(uint32_t));
*stringaling = "fun";
This is not valid code. You are trying to assign to a const variable, which is illegal. Then you are trying to assign an array of characters to a character. And finally, even if you had a non-const array of characters of the right size, you still can't assign arrays, because they're not first-class values.
Try using
char *stringaling = malloc(sizeof(uint32_t));
strcpy(stringaling, "fun");
...instead, and see if that doesn't work better. Note, however, that it's pretty much accidental that (at least usually) sizeof(uint32_t) happens to be the right size to hold "fun". You normally don't want to do that.
Alternatively, you may want:
char const *stringaling = "fun";
or:
char stringaling[] = "fun";
The assignment you had won't work though -- C has only the very most minimal support for strings built into the language; most operations (including copying a string) are normally done via library functions such as strcpy.
"fun" is a string literal, which is essentially a const char *.
stringaling is also a const char *, so your third line is trying to assign a const char * to a const char, which is not going to fly.
If it's a constant string, you can just do this:
const char *stringaling = "fun";
If your input string is dynamic, you can do this:
char *stringaling= (char *) malloc(strlen(inputString)+1);
strcpy(stringaling, inputString);
Obviously, if you malloc it, you need to free it, or feel the wrath of a memory leak.
If you really want to initialize the char *, you could write this instead:
const char *stringaling = "fun";
And here's some reference.
without all the stuff you can also use:
newval = protobuf_writeString (buffer, "fun" );
First problem:
const char *stringaling= (const char *) malloc(sizeof(uint32_t));
Several problems on this line.
First of all, you don't want to declare stringaling as const char *; you will not be able to modify whatever stringaling points to (IOW, *stringaling will not be writable). This matters since you want to copy the contents of another string to the location pointed to by stringaling. Drop the const keyword.
Secondly, malloc(sizeof(uint32_t)) just happens to allocate enough bytes (4) for this particular string, but it's not clear that you meant to allocate 4 bytes. When allocating memory for an array (and strings are arrays), explicitly indicate the number of elements you intend to allocate.
Finally, casting the result of malloc is considered bad practice in C. The cast will suppress a useful diagnostic message if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope. As of the 1989 standard, malloc returns void *, which can be assigned to any other object pointer type without needing to cast. This isn't true in C++, so a cast is required there, but if you're writing C++ you should be using new instead of malloc anyway.
So, change that line to read
char *stringaling = malloc(LEN); // or malloc(LEN * sizeof *stringaling), but
// in this case that's redundant since
// sizeof (char) == 1
where LEN is the number of chars you want to allocate.
The general form for a malloc call is
T *p = malloc (N * sizeof *p);
where T is the base type (int, char, float, struct ..., etc.), and N is the number of elements of type T you want to allocate. Since the type of the expression *p is T, sizeof *p == sizeof(T); if you ever change the type of p, you don't have to replicate that change in the malloc call itself.
Second problem:
*stringaling = "fun";
Again, there are several issues at play. First, you cannot assign string values using the = operator. String literals are array expressions, and in most contexts array expressions have their type implicitly converted ("decay") from "N-element array of T" to "pointer to T". Instead of copying the contents of the string literal, you would be simply assigning a pointer to the first character in the string.
Which would "work" (see below), except that you're dereferencing stringaling in the assignment; the type of the expression *stringaling is const char (char after making the change I indicated above), which is not compatible for assignment with type char *. If you drop the dereference operator and write
stringaling = "fun";
you'd fix the compile-time error, but now you have another problem; as mentioned above, you haven't copied the contents of the string literal "fun" to the memory block you allocated with malloc; instead, you've simply copied the address of the string literal to the variable stringaling. By doing so, you lose track of the dynamically-allocated block, causing a memory leak.
In order to copy the string contents from one place to another, you'll have to use a library function like strcpy or strncpy or memcpy, like so:
strcpy(stringaling, "fun");
If stringaling doesn't need to live on the heap (for example, you're only using it within a single function and deallocating it before returning), you could avoid memory management completely by declaring it as a regular array of char and initializing it with "fun":
char stringaling[] = "fun";
This is a special case of initializing an array in a declaration, not an assignment expression, so the = does copy the contents of the string literal to the stringaling array. This only works in an array declaration, however. You can later modify the array with other string values (up to 3 characters plus the 0 terminator), but you'd have to use strcpy again:
strcpy(stringaling, "one");
If you don't need to modify the contents of stringaling, you could just do
const char *stringaling = "fun";
This copies the address of the string literal "fun" to the variable stringaling. And since attempting to modify the contents of a string literal invokes undefined behavior, we do want to declare stringaling as const char * in this case; that will prevent you from accidentally modifying the string literal.
Related
I am trying to convert a string in C (using the string.h library) into a const char array.
int len = sizeof(the_string);
const char *char_array = malloc(len);
strcpy(char_array, the_string);
I have pored through the string.h method file and googled it but things keep coming up in C++. Any advice would be greatly appreciated, thank you!!!
This declaration of a pointer
const char *char_array;
means that you may not change the memory pointed to by the pointer using the pointer.
You could make the pointer itself a constant object like
char * const char_array = malloc( some_size );
In this case you may not reassign the pointer itself but you may change the memory pointed to by the pointer.
Take into account that the expression sizeof(the_string) does not make a great sense if you are going to know the length of a string stored in a character array because in general a character array can be much larger than the stored string in it. Instead you should write
size_t len = strlen( the_string );
Using the expression sizeof(the_string) makes a sense in declarations such this
char the_string[] = "Hello";
that is when the size of a character array is determined by the size of a string literal used as an initializer.
I need to convert a string (char*) to an array of __uint8_t. I know the latter is an alias of unsigned char but I can't figure it out how to proper convert it.
Example:
char *ssid = "XXXXX";
This is need cause I have to call an API that accepts only an array of __uint8_t and not char*.
struct WifiConfig {
uint8_t ssid[32];
uint8_t password[64];
};
struct WifiConfig wifi_config;
wifi_config.ssid = ???
If I try to cast:
wifi_config.ssid = (__uint8_t *) ssid;
I get the follow error:
error: assignment to expression with array type
wifi_config.ssid = (__uint8_t *) ssid;
Sorry if that's a silly question, last time I've played with C I was a teen.
Thanks in advance!
Just cast:
const char *name = "My Full Name";
yourAPIFunction((__uint8_t *) name);
Note: this violates const-correctness. You have to make sure yourAPIFunction doesn't mutate name. If it does, then you'll need to memcpy (and free!) it to a local variable, and provide it that, so its mutations don't effect the pooled-string used by any other users of "My Full Name".
Response to your (completely different) updated question:
Those arrays have their storage in-line, they're not pointers to the heap like a typical char *.. You need to copy the contents of your string into them:
// ssid must be at most 31 chars (plus NUL terminator)
// password must be at most 63 chars (plus NUL terminator)
struct WifiConfig new_wifi_config(char *ssid, char *password) {
struct WifiConfig wifi_config;
memcpy(wifi_config.ssid, ssid, strlen(ssid)+1)
memcpy(wifi_config.password, ssid, strlen(ssid)+1)
return wifi_config;
}
I need to convert a string (char*) to an array of __uint8_t. I know
the latter is an alias of unsigned char but I can't figure it out how
to proper convert it.
Being pedantic -- because it matters here -- a C string is not a char *. Rather, it is a null-terminated array of char. These are accessed and handled primarily via pointers of type char *, largely because that's how one works with arrays in C.
Thus, no, you do not want to convert a char * to an array. It appears that what you want to do is copy the contents of the array to which it points. For your particular purpose I would use the strncpy() function:
strncpy((char *) wifi_config.ssid, ssid, sizeof(wifi_config.ssid));
Note well that with that code, if ssid is longer than wifi_config.ssid can accommodate then the latter will end up being unterminated, and that otherwise its tail will be filled out with null bytes. Given the type of that array, such behavior may be precisely what is needed. If you want to ensure null termination, however, then simply overwrite the last byte of the array with a 0 after the strncpy().
I am practicing allocation memory using malloc() with pointers, but 1 observation about pointers is that, why can strcpy() accept str variable without *:
char *str;
str = (char *) malloc(15);
strcpy(str, "Hello");
printf("String = %s, Address = %u\n", str, str);
But with integers, we need * to give str a value.
int *str;
str = (int *) malloc(15);
*str = 10;
printf("Int = %d, Address = %u\n", *str, str);
it really confuses me why strcpy() accepts str, because in my own understanding, "Hello" will be passed to the memory location of str that will cause some errors.
In C, a string is (by definition) an array of characters. However (whether we realize it all the time or not) we almost always end up accessing arrays using pointers. So, although C does not have a true "string" type, for most practical purposes, the type pointer-to-char (i.e. char *) serves this purpose. Almost any function that accepts or returns a string will actually use a char *. That's why strlen() and strcpy() accept char *. That's why printf %s expects a char *. In all of these cases, what these functions need is a pointer to the first character of the string. (They then read the rest of the string sequentially, stopping when they find the terminating '\0' character.)
In these cases, you don't use an explicit * character. * would extract just the character pointed to (that is, the first character of the string), but you don't want to extract the first character, you want to hand the whole string (that is, a pointer to the whole string) to strcpy so it can do its job.
In your second example, you weren't working with a string at all. (The fact that you used a variable named str confused me for a moment.) You have a pointer to some ints, and you're working with the first int pointed to. Since you're directly accessing one of the things pointed to, that's why you do need the explicit * character.
The * is called indirection or dereference operator.
In your second code,
*str = 10;
assigns the value 10 to the memory address pointed by str. This is one value (i.e., a single variable).
OTOTH, strcpy() copies the whole string all at a time. It accepts two char * parameters, so you don't need the * to dereference to get the value while passing arguments.
You can use the dereference operator, without strcpy(), copying element by element, like
char *str;
str = (char *) malloc(15); //success check TODO
int len = strlen("Hello"); //need string.h header
for (i = 0; i < len; i ++)
*(str+i)= "Hello"[i]; // the * form. as you wanted
str[i] = 0; //null termination
Many string manipulation functions, including strcpy, by convention and design, accept the pointer to the first character of the array, not the pointer to the whole array, even though their values are the same.
This is because their types are different; e.g. a pointer to char[10] has a different type from that of a pointer to char[15], and passing around the pointer to the whole array would be impossible or very clumsy because of this, unless you cast them everywhere or make different functions for different lengths.
For this reason, they have established a convention of passing around a string with the pointer to its first character, not to the whole array, possibly with its length when necessary. Many functions that operate on an array, such as memset, work the same way.
Well, here's what happens in the first snippet :
You are first dynamically allocating 15 bytes of memory, storing this address to the char pointer, which is pointer to a 1-byte sequence of data (a string).
Then you call strcpy(), which iterates over the string and copy characters, byte per byte, into the newly allocated memory space. Each character is a number based on the ASCII table, eg. character a = 97 (take a look at man ascii).
Then you pass this address to printf() which reads from the string, byte per byte, then flush it to your terminal.
In the second snippet, the process is the same, you are still allocating 15 bytes, storing the address in an int * pointer. An int is a 4 byte data type.
When you do *str = 10, you are dereferencing the pointer to store the value 10 at the address pointed by str. Remind what I wrote ahead, you could have done *str = 'a', and this index 0 integer would had the value 97, even if you try to read it as an int. you can event print it if you would.
So why strcpy() can take a int * as parameter? Because it's a memory space where it can write, byte per byte. You can store "Hell" in an int, then "o!" in the next one.
It's just all about usage easiness.
See there is a difference between = operator and the function strcpy.
* is deference operator. When you say *str, it means value at the memory location pointed by str.
Also as a good practice, use this
str = (char *) malloc( sizeof(char)*15 )
It is because the size of a data type might be different on different platforms. Hence use sizeof function to determine its actual size at the run time.
This is probably a really easy question but I can not seem to find an explicit answer online. Say a had a pointer to an array declared as:
static char newMessage[400];
char *p = &newMessage;
(I don't know if this is right) How would I go about manipulation the newMessage array using only the pointer. I am doing this because a C cannot return an array but can return a pointer to an array. please be gentle, I'm new
Your code is almost right; the only problem is that you have mismatched pointer types. You want:
char *p = newMessage;
Not:
char *p = &newMessage;
The latter tries to initialize p, a char * variable, with a value of type char (*)[400], which isn't valid C.
After you've created and initialized p, you can just use it however you'd like:
p[6] = 12;
Or something like that.
Just point the pointer to the array
char* p = newMessage ;
And return it from a function.
You use it the same as you would use the array it points to.
newMessage[2] = '\0'
p[2] = '\0'
When you declare an array like static char newMessage[400], the identifier newMessage is substituted by the address of the first element of the array, and it behaves like a pointer.
char* p= newMessage;
char* q= "Hi, world";
newMessage[4]= 'x';
p[4]= 'x';
*(newMessage + 2)= 0;
*(p+2)= 0;
strlen(newMessage);
strlen(q);
strcmp(newMessage, "Hi world");
strcmp(p, q);
are all valid expressions.
Note that in the last four function calls, you are not passing arrays, but pointers to the first character of the string. And by convention, the functions scan the memory until they find a null byte terminator.
Actually, it should be char *p = newMessage; .The char[] behaves similar to char*.
You'll later modify it by how you usually modify any pointer.
BTW, this is very basic so it's better you read a tutorial.
Also, since you asked this, if you're planning to return a pointer to the array, the array better not be allocated on the stack. It should be heap-allocated (it's in your case since static)
You cannot actually manipulate the array, as arrays are no first class type in c.
Almost anything you care to do with the array name, will make it degenerate to a pointer. The exception being sizeof, so you can get the element count using sizeof array/sizeof *array.
What you can do, is change the values of the array elements. Use pointer arithmetic and dereferencing *. The index operator a[b] is syntactic sugar for *(a+b).
Also, you can use library functions (or your own), which accept pointers.
I need to hold an array of C strings. Now I know C strings are just an array of chars so essentially what I want is a 2d array of chars. The strings I'm trying to store will also never exceed 6 characters. My plan is to initialize a char array with 50 "string slots" and then if I hit 50 strings reallocate the array's memory to double it's capacity. I've tried something simple like:
int main() {
char strings[50][6];
strings[0] = "test";
printf("The string is: %s", strings[0]);
return(0);
}
But, when I go to compile it I get the following error:
test.c: In function ‘main’: test.c:3:
error: incompatible types when
assigning to type ‘char[6]’ from type
‘char *’ test.c:4: warning:
incompatible implicit declaration of
built-in function ‘printf’
Can anyone point in me in the right direction?
strncpy(strings[0], "test", 6); unless your C library has strlcpy(). However if you are going to need to vary the size of the storage, you're better off using a char ** with malloc(), realloc() and free().
One can't assign arrays directly in that way. In your current case, you would need to do something like...
strcpy (strings[0], "test");
It would be more idiomatic to use an array of pointers, though. Have a look at p111 and onwards of K & R.
Use strncpy (if at all possible) or strcpy for your assignment.
First the easy part. You do need to
#include <stdio.h>
to get rid of the incompatible printf warning. This has to do with the way the standard says C works, which is to allow you to make some function that is unlike the standard printf, the implicit declaration of that function with its signature (incorrectly) guessed by the compiler, and the compiler knowing that while you can define a different printf you probably didn't actually mean to.
Ok, now the more complicated part. Arrays in C are a little special. The can evaluate to pointer literals (which can't be assigned to, which is similar to trying to 6 = 4;), or they can evaluate to an entire array, depending on context. Usually they are pointer literals, but in this case strings[0] is seen as an array, which is why you get the error you got rather than one stating that strings[0] was an invalid l-value (left-value, meaning something that can be on the left side of a =). Either way you can't copy a character pointer literal (which is what "test" evaluates to) to an array. When you do this on the line where you declare a string (char array) the compiler treats it differently, though, which can cause some confusion. Anyway, you need to either use strcpy to copy the characters that make up "test" or initialize strings[0] to "test" like this:
char strings[50][6] = { "test" }; // only initializes the first member of the array
You can't assign array contents using the = operator. First of all, an array object cannot be a target of the assignment operator (Online C Standard, draft n1256, section 6.5.16.1, paragraph 1). strings[0] is an array object of type char [6], so it can't appear on the LHS of the = operator.
Second of all, when an array expression is not an operand of either the sizeof or address-of & operators and is not a string literal being used to initialize the contents of another array, the type of the expression is implicitly converted ("decays") from "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element in the array (section 6.3.2.1, paragraph 3).
The string literal "test" is a 5-element array of char (const char in C++) with static extent (meaning the memory for it is allocated at program startup and held until the program exits). However, when it appears in the expression
strings[0] = "test";
its type is converted from "5-element array of char" to "pointer to char" and its value is the address of the first element, so what you wind up doing is attempting to assign a pointer value to an array object, which is not a compatible type; bad juju, over and above not being able to assign an array object anyway.
If you want to copy the contents of one array to another, then you will need to either assign each array element individually, such as
strings[0][0] = 't';
strings[0][1] = 'e';
strings[0][2] = 's';
strings[0][3] = 't';
strings[0][4] = 0;
or even
size_t len = strlen("test");
size_t i;
for (i = 0; i < sizeof strings[0] - 1 && i < len; i++)
strings[0][i] = "test"[i]; // yes, you can subscript a string literal
strings[0][i] = 0;
or use a library function like memcpy(), strcpy(), strncpy(), strcat(), sprintf(), etc.:
strcpy(strings[0], "test");
or
strncpy(strings[0], "test", sizeof strings[0] - 1); // -1 to leave room
// for 0 terminator
// if necessary
or
sprintf(strings[0], "%*s", (int) sizeof strings[0] - 1, "test");
Note that you can initialize the array's contents when you declare it, like so:
char foo[] = "test"; // foo is implicitly sized to 5 (+1 for 0 terminator)
int bar[] = {1,2,3,4,5}; // again, size is implied from initializer
float f[3] = {1.0, 2.0, 3.0}; // Initializer cannot contain more items than
// array is sized for
I see there's a merry war over the use of strcpy() vs. strncpy() in the comments to another answer; my position is to use whichever one is appropriate to the given situation. If you know that your buffers are big enough to handle the largest possible input, use strcpy(). If not, use strncpy(), but be aware that you may have to add the 0 terminator manually.
The problem you have is in the way that the compiler interprets the statement char strings[50][6];
Instead of what you hoped, a char array with 50 slots for 6 char strings, you got a char array of single chars with dimesions 50x6.
Rather than char strings[50][6];, the way you want to initialise your array is as follows (I only know how to do this on the heap, sorry):
char ** strings[50] = malloc(50 * sizeof(char *));
for(int i = 0; i < 50; ++i)
{
strings[i] = malloc(50 * 6 * sizeof(char *));
}
Don't forget to clean with frees afterwards.
EDIT: And as said above. Before your main method. Inlcude the line #include <stdio.h>. This is where the printf() function is located.