I'm confused by this snippet from the book I'm reading. Text strings are put into a char array. There are four words, with four elements in the array. Wait, but that means a single char element is containing a whole text string. I'm certain chars can only handle a single character. Here's the code.
const char *words[4] = { "aardvark", "abacus",
"allude", "zygote" };
So what gives? How can the author be using chars to store whole strings? I know the solution must be blindingly obvious, but I just can't see it. Also, what's with the const keyword? Why would it need to be read only if all we plan to do with this array is count the length of each word using strlen()?
The code does not use chars to store strings, note that the declaration is an array of char *.
A char can hold a single character, and a char * can be used to point to the first element of an array of characters, which can hold a standard C string. This is an important C fundamental: see a char * and you should immediately think of null-terminated C strings.
Similarly, an int * can be used to refer to an entire array of int, by holding the address of the first int in the array. int* can be subscripted the same as an array declared using [].
A char * can also be used to simply hold the address of a single character - i.e. not the first character in a null terminated string.
How can the author be using chars to store whole strings?
he can't. You notice the asterisk, right?
The point your missing is the *.
char letter = 'a'; //stores a single character
char *word = "bigger"; //stores a string literal
this means word is really:
word ---> [b][i][g][g][e][r][\0]
pointing to a bunch of chars (or a "string" of chars). In your example the author defined:
const char *words[4] = { "aardvark", "abacus", "allude", "zygote" };
So you have 4 strings of chars, which are constant. The const was the author's choice to add that on there... it could have been left off. It's just a safeguard, a note to the compiler (and author) that these values were not ment to be modified.
Related
I am looking for a solution for my problem (newbie here).
I have an array of strings (char** arrayNum) and I would like to store the number of elements of that array at the first index.
But I can't find the right way to do convert the number of elements as a string (or character).
I have tried itoa, casting (char), +'0', snprintf ... nothing works.
As every time I ask a question on Stack Overflow, I am sure the solution will be obvious. Thanks in advance for your help.
So I have an array of strings char** arrayNum which I populate, leaving the index 0 empty.
When I try to assign a string to arrayNum[0]:
This works: arrayNum[0] = "blabla";
This does not work: arrayNum[0] = (char) ((arraySize - 1)+'0');
I have tried countless others combinations, I don't even remember...
arrayNum can be thought of as an array of strings (char *). So you will naturally have trouble trying to assign a char (or indeed any type other than char *) to an element of this array.
I think it would preferable to store the length of the array separately to the array. For example, using a struct. To do otherwise invites confusion.
If you really, really want to store the length in the first element, then you could do something like:
arrayNum[0] = malloc(sizeof(char));
arrayNum[0][0] = (char) ((arraySize - 1)+'0');
This takes advantage of the fact that arrayNum is strictly an array of pointers and each of those pointers is a pointer to a char. So it can point to a single character or an array of characters (a "string").
Compare this for clarity with (say):
struct elements {
int length;
char **data;
};
arrayNum is not an "array of strings."
It might be useful for you to think about it that way, but it is important for you to know what it really is. It is an array of pointers where each pointer is a pointer to char.
Sometimes a pointer to char is a "string," and sometimes it's a pointer into the middle of a string, and sometimes it's just a pointer to some character somewhere. It all depends on how you use it.
The C programming language does not really have strings. It has string literals, but a string literal is just a const array of characters that happens to end with a \000. The reason you can write arrayNum[0] = "blabla"; is because the value of the string literal "blabla" is a pointer to the first 'b' in "blabla", and the elements of the arrayNum array are pointers to characters.
It's your responsibility to decide whether arrayNum[i] points to the first character of some string, or whether it just happens to point to some single character; and it's your responsibility to decide and keep track of whether it points to something that needs to be freed() or whether it points to read-only memory, or whether it points to something on the stack, or whether it points to/into some staticly allocated data structure.
The language doesn't care.
My Google protobuf-c proto file looks like this:
message foo{
required uint32 addresscount= 1;
repeated string destination_hops= 2;
}
I want an array of strings and addresscount is supposed to give the count of array elements.
The generated protobuf-h file is
struct _foo
{
ProtobufCMessage base;
uint32_t addresscount;
size_t n_destination_hops;
char **destination_hops;
};
I assume that n_destination_hops is the number of times the string destination_hops appears in the message. I had kept addresscount for that purpose and i guess thats not required. My question is this:
char **destination_hops is a pointer to an array of char * pointers. Each index can be of different length. How will protobuf know the size of each char * pointer when it has packed this into a stream. Does protobuf assume that all destination_hops would be of the same size and is that given by size_t n_destination_hops?
DOUBT 2:
char ** destination_hops is an array of char * pointers.
This means i can look at it as char *destination_hops[0], char *destination_hops[1], etc
If this is correct then shouldn't i be able to set char *destination_hops[0] = "abc".
When i do that i get a segmentation fault.
Any idea why?
I assume that n_destination_hops is the number of times the string destination_hops appears in the message.
Yep.
I had kept addresscount for that purpose and i guess thats not required.
Right.
char **destination_hops is a pointer to an array of char * pointers. Each index can be of different length. How will protobuf know the size of each char * pointer when it has packed this into a stream.
In the wire representation of the string, it is preceded by the string's length, coded as a packed integer. In memory, they are just ordinary zero-terminated C strings, so:
NUL is not a valid character in the string
the length can be computed with strlen
Protobuf requires that the value of a string be a sequence of UTF-8 encoded characters. If you want to include NUL or bytes which are not part of a valid UTF-8 sequence, use bytes instead of string. If you do that, the in-memory datastructure will include an explicit length.
Shouldn't i be able to set char *destination_hops[0] = "abc"
I suppose you mean that you should be able to write:
destination_hops[0] = "abc";
That's valid C, but it requires that destination_hops have at least one element. A newly initialized foo will have n_destination_hops = 0; and destination_hops = NULL;, in which case trying to access destination_hops[0] will try to dereference NULL, which is a segfault. (Or UB, if you prefer.9
I'm on an embedded system so do not have access to a most of the standard library. I have a struct which contains char values.
I have a simple print function which simply outputs an unsigned char string to an attached screen. It does not support format specifiers like printf does.
This is the struct:
typedef struct my_options{
char test;
} my_options;
And this is where I'm trying to output the value:
struct my_options options;
print(options.test); //Here I get "implicit conversion of int to ptr"
How do I achieve this?
Create a char array to hold your char and then print it:
char wrapper[2];
wrapper[0] = options.test;
wrapper[1] = '\0';
print(wrapper);
Create a temporary 2-character long string that has the character to print, and then the terminator. Then pass that string to your print() function:
void print_options(const struct my_options *opt)
{
char tmp[] = { opt->test, '\0' };
print(tmp);
}
your member test if of the type char, where the print function expects an argument of the type const char * (assuming the const bit here, but that's what I'd expect, this as an asside). Passing the address of test then would seem like the appropriate solution, but is it?
No, of course it isn't. There is no absolute guarantee that the next byte after test will be '\0' (a string terminating char). What you, then, ought to do is create a wrapper string:
char char_wrapper[2] = {};//initializes according to standard
//but as Lundin pointed out, self-documenting code is important:
char_wrapper[0] = options.test;?
char_wrapper[1] = '\0';//explicit, so it's clear what this code does
print(char_wrapper);
That should work just fine.
You can, of course, write this as a one-liner:
char char_wrapper[2] = {options.test, '\0'};//same as before, only in 1 statement
print(char_wrapper);//print "string"
That should do it, really. You don't even have to explicitly write the terminating char, since the standard specifically states:
An array of character type may be initialized by a character string literal, optionally
enclosed in braces. Successive characters of the character string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
6.7.8 Initialization cf p. 138, semantics, point 14
Be that as it may, I'd still prefer to browse the web, or just set about writing your own minor implementation of printf so you can use format specifiers. Heck, it's one of the first exercises in the K&R book, and there's tons of solutions floating about on the net. check those out, and adapt them to your specific needs.
Or, perhaps define print to accept a size_t argument, to specify how many chars you want to pass to the output stream. and call it like so print(options.test, 1);
print is looking for a char*. You are passing an char which can also be represented as an int. Thus, the function is trying to implicitly convert an int to a pointer as it is telling you.
char ptr[2];
ptr[0] = options.test;
ptr[1] = '\0';
Would wrap the char into a char array, which in C will decay into a pointer when you pass it to a function.
how do i Initialize my code if all im using are words and no numbers?
I have been trying to just use char * but it is saying that its still not initialized
char *Carson;
printf("Enter a name:\n");
scanf("%s",Name);
printf("%s Hello Carson\n", Carson);
You either have to allocate memory dynamically and assign it to Carson (see e.g. `malloc? ), or make it an array. There's no way around it. And for that, the code must contain a number. The number could be input from the user though, so you won't have any actual numbers in the source.
Remember that in C all strings need an extra terminator character (added automatically by scanf) so remember to add space for it.
A solution without any number, I don't think this must be used for practical applications, just a hack
char Carson[sizeof(long long) * sizeof(long long)];
printf("Size = %d\n", sizeof Carson);
printf("Enter a name:\n");
scanf("%s",Carson);
printf("%s Hello Carson\n", Carson);
In my system it create a char array of 64 bytes = 8 * 8, the size of long long in most systems is 8 bytes although it's size depends on your compiler and operating system
you might like to initialize Carson like this:
char *Carson = malloc(sizeof(char)*200);/* for 200 characters */
Don't forget to add \0 terminator and also, donot forget to free it once you are done using it.
In order to initialize variables in C you need to use constants values, that is, expressions whose value can be known at compile time.
For integer or float types you can use mathematical formulas involving only constant operands, thus you can obtain still a constant value that can be used in a initiaiization.
What you call "words" have been called better "strings".
In C you are able to use strings that are constant at compile time, also called "string literals".
A string literal has to be indicated surrounded by quotes, like these examples:
"Hello world!"
"Peter & John"
"user#gmail.com"
and so on.
There are some rules that you need to remember: some special characters have "escape sequences" to be used inside a string literal.
Now you can use that string literals in order to initialize a char* variable:
char *name = "Mr. Smith";
char *city = "Amsterdam";
The result of the initialization gives a C string style, that is, an array of char object, whose length is the amount of quoted characters in the string literal, plus 1, because a null character is added at the end. Thus, in memory you have:
char *city ----> |A|m|s|t|e|r|d|a|m|\0|
Thus, city points to an array of 10 chars.
The last character, \0, means "null character", whose ASCII code is 0. Since it corresponds to a non-printable character, it has to be indicated with the escape sequence \0.
For more information, take a look on these websites:
Escape sequences in C
Storage of string literals
If you initialize a pointer to char object to a string literal, the compiler reserves memory automatically for you, son you don't need any malloc() at all.
However, you cannot modify the characters of such a string.
If you are interested in modify the characters, you can use better un array of char object:
char name[30] = "Schwarzenegger";
The array reserves 30 chars for the string literal "Schwarzenegger".
Only the first 14 are used for the string, plus 1 holding the null character attached at the end.
The rest of chars of the array have dummy information, but there is no problem because they are not printed. (The standard library functions always stop processing the string when they encounter a null character).
EDITED More information.
About your particular error message: "lack of initialization", the problem is that in the definition of the pointer to char object:
char *name;
you only have a "pointer to" an undefined block of memory.
You have to specify the array of char that name will be point to.
If you initialize with a string literal, there is not any problem, because the address of the string literal is passed to name.
But, since you are planning to use name for data input by means of scanf(), you have to allocate memory enough. You can do that other users have explained yet in their answers, that is, by using malloc().
I think there is need to do changes in your code,
char Carson = NULL;
Carson = (char)malloc(sizeof(char)*256);
printf("Enter a name:\n");
scanf("%s",Carson );
printf("%s Hello Carson\n", Carson);
in place of 256 u can use whatever value you want.
let me know if it works.
While digging in some C source code I found that fragment of code
char **words
I know that single asterisk before variable name "points" to pointer, but what is the purpose of those two asterisks ?
It is a pointer to a pointer.
It is used primarily when you use an array of character strings.
For example: you have char sample[5][5]; - this can store 5 strings of length 4;
If you need to pass it to a function, func(sample);
And the function definition of such a function would be func(char **temp);
// your imagination is the limit
char letter;
char *word; // sequence of letters
char **sentence; // sequence of words
char ***paragraph; // sequence of sentences
char ****book; // sequence of paragraphs
char *****library; // sequence of books
The data structure is probably not the best to represent the concept: this is just an illustration.
simple dude!
it points to the pointer thats it
**a points to the pointer *a
thats it.
For more information you can google it