So I am in the process of learning C and am slightly confused by this statement on the website I am learning from.
if you have
char ch_arr[3][10] = {
"spike",
"tom",
"jerry"
};
It says that.
The ch_arr is a pointer to an array of 10 characters or int(*)[10]
However, what is the meaning of int(*)[10], if this is a character array, why is the pointer not a char type?
Thanks in advance, sorry if the question is bad, I'm trying to get better at asking questions.
This is a two-dimensional array. Each string (e.g. "spike") is a character array. That means that it's basically an array containing arrays.
char ch_arr[3][10] = {"spike", "tom", "jerry"};
The two-dimensional array ch_arr can then be converted to a pointer. In both C and C++ array to pointer conversion applies to every array automatically on access, so the pointer points to the first element, which is of type char[10] in this case. Therefore the pointer is of type char(*)[10], as Keith Thoumpson pointed out in the comments.
And concerning the website you are using... It contains some mistakes, so I would use a different source instead.
Related
This question already has answers here:
C pointer to array/array of pointers disambiguation
(13 answers)
Closed last month.
This post was edited and submitted for review last month and failed to reopen the post:
Original close reason(s) were not resolved
When my professor taught about double-pointers and two-dimensional arrays, he wrote like this in his lesson:
char* words[]={"one","two","three"};
Later he introduced another kind of writing style:
int (*table)[3];
But after class, when I try writing on my own, I wrote:
char (*word)[6]={"one","two","three"};
Then it came error:
the error
Furthermore, if I wrote like:
char table[][6]={"one","two","three"};
char (*word)[6]=table;
It ran successfully, which meant it just couldn't be initialized(?)
Could you please tell me the difference between
char* words[]={"one","two","three"};
and
char (*word)[6]={"one","two","three"};
and tell me why the latter one encountered with error?
I googled and searched the error info in the website, but found nothing useful. Neither can my classmates answer my questions, I have asked my prof but he hasn't answered me yet.
I have found the difference between the two styles, the only question now is the cause of the error!
char* words[]={"one","two","three"}; This is a one-dimensional array of pointers to char. Since they are pointing to string literals, it should most often be written as const char* since we can't write to a pointed-at string literal.
int (*table)[3]; This is a different beast, a single pointer to an array of type int [3]. It has no relation to arrays of pointers. These kind of pointers are often called "array pointers" and they are not really a beginner topic, so why your professor introduced them this early, I don't know.
char (*word)[6]={"one","two","three"}; Won't work since you declared a pointer to an array of type char [6] then try to initialize it with 3 string literals.
In formal standard C terms, a single variable or pointer is known as a "scalar", whereas an array or struct is known as an "aggregate". Therefore a char(*)[6] is a scalar and you may only give one single initializer to a scalar, not 3 as in your case, hence the compiler error. (You may however surround that single initializer with braces, int a={1}; is for example equivalent to int a=1;.)
char table[][6]= This is a true 2D array and after initialization it will get the type char[3][6]. You allocated exactly 3*6 = 18 bytes in memory and no pointers. But you actually allocated memory to hold the data, instead of just pointing at it, meaning that each string can be changed. (Although it can't be longer than 5 characters + 1 null terminator.) So the string literals in this case aren't just pointed at, they get copied into the 2D array upon initialization.
char (*word)[6]=table; This works because any array, table in this case, "decays" into a pointer to its first element when used in most expressions. The first element of an array char [3][6] is of type char [6]. A pointer to the first element is char(*)[6] so the code is fine.
char string1[3][4]={"koo","kid","kav"}; //This is a 2D array
char * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters
//I want to know differences between string1Ptr(pointer to array mentioned in question) and string(array of pointers mentioned in question). I only typed string1 here to give string1Ptr an address to strings
Besides the fact that string can point to strings of any size and string1Ptr can only point to strings of size 4 only(otherwise pointer arithmetic would go wrong), I don't see any differences between them.
For example,
printf("%s\n", string1[2]); // All print the same thing, ie, the word "kav"
printf("%s\n", string1Ptr[2]);
printf("%s\n", string[2]);
They all seem to perform the same pointer arithmetic.(My reason for assuming string and string1Ptr are almost similar besides for the difference I stated above)
So what are the differences between string and string1Ptr? Any reason to use one over the other?
PS: I'm a newbie so please go easy on me.
Also, I did check C pointer to array/array of pointers disambiguation, it didn't seem to answer my question.
char string1[3][4]={"koo","kid","kav"}; //This is a 2D array
char * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters
Besides the fact that string can point to strings of any size and
string1Ptr can only point to strings of size 4 only(otherwise
pointer arithmetic would go wrong), I don't any differences between
them.
They are absolutely, fundamentally different, but C goes to some trouble to hide the distinction from you.
string is an array. It identifies a block of contiguous memory wherein its elements are stored. Those elements happen to be of type char * in this example, but that's a relatively minor detail. One can draw an analogy here to a house containing several rooms -- the rooms are physically part of and exist inside the physical boundaries of the house. I can decorate the rooms however I want, but they always remain the rooms of that house.
string1Ptr is a pointer. It identifies a chunk of memory whose contents describe how to access another, different chunk of memory wherein an array of 4 chars resides. In our real estate analogy, this is like a piece of paper on which is written "42 C Street, master bedroom". Using that information, you can find the room and redecorate it as you like, just as in the other case. But you can also replace the paper with a locator for a different room, maybe in a different house, or with random text, or you can even burn the whole envelope, without any of that affecting the room on C Street.
string1, for its part, is an array of arrays. It identifies a block of contiguous memory where its elements are stored. Each of those elements is itself an array of 4 chars, which, incidentally, happens to be just the type of object to which string1Ptr can point.
For example,
printf("%s\n", string1[2]); // All print the same thing, ie, the word "kav"
printf("%s\n", string1Ptr[2]);
printf("%s\n", string[2]);
They all seem to perform the same pointer arithmetic.(My reason for
assuming string and string1Ptr are almost similar besides for the
difference I stated above)
... and that is where C hiding the distinction comes in. One of the essential things to understand about C arrays is that in nearly all expressions,* values of array type are silently and automatically converted to pointers [to the array's first element]. This is sometimes called pointer "decay". The indexing operator is thus an operator on pointers, not on arrays, and indeed it does have similar behavior in your three examples. In fact, the pointer type to which string1 decays is the same as the type of string1Ptr, which is why the initialization you present for the latter is permitted.
But you should understand that the logical sequence of operations is not the same in those three cases. First, consider
printf("%s\n", string1Ptr[2]);
Here, string1Ptr is a pointer, to which the indexing operator is directly applicable. The result is equivalent to *(string1Ptr + 2), which has type char[4]. As a value of array type, that is converted to a pointer to the first element (resulting in a char *).
Now consider
printf("%s\n", string1[2]);
string1 is an array, so first it is converted to a pointer to its first element, resulting in a value of type char(*)[4]. This is the same type as string1Ptr1, and evaluation proceeds accordingly, as described above.
But this one is a bit more different:
printf("%s\n", string[2]);
Here, string is a pointer, so the indexing operation applies directly to it. The result is equivalent to *(string + 2), which has type char *. No automatic conversions are performed.
Any reason to use one over the other?
Many, in both directions, depending on your particular needs at the time. Generally speaking, pointers are more flexible, especially in that they are required for working with dynamically allocated memory. But they suffer from the issues that
a pointer may be in scope, but not point to anything, and
declaring a pointer does not create anything for it to point to. Also,
even if a pointer points to something at one time during an execution of the program, and its value is not subsequently written by the program, it can nevertheless stop pointing to anything. (This most often is a result of the pointer outliving the object to which it points.)
Additionally, it can be be both an advantage and a disadvantage that
a pointer can freely be assigned to point to a new object, any number of times during its lifetime.
Generally speaking, arrays are easier to use for many purposes:
declaring an array allocates space for all its elements. You may optionally specify initial values for them at the point of declaration, or in some (but not all) cases avail yourself of default initialization.
the identifier of an array is valid and refers to the array wherever it is in scope.
Optionally, if an initializer is provided then an array declaration can use it to automatically determine the array dimension(s).
* But only nearly all. There are a few exceptions, with the most important being the operand of a sizeof operator.
The difference between string1 and string is the same as the difference between:
char s1[4] = "foo";
char *s2 = "foo";
s1 is a writable array of 4 characters, s2 is a pointer to a string literal, which is not writable. See Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?.
So in your example, it's OK to do string1[0][0] = 'f'; to change string1[0] to "foo", but string[0][0] = 'f'; causes undefined behavior.
Also, since string is an array of pointers, you can reassign those pointers, e.g. string[0] = "abc";. You can't assign to string1[0] because the elements are arrays, not pointers, just as you can't reassign s1.
The reason that string1Ptr works is because the string1 is a 2D array of char, which is guaranteed to be contiguous. string1Ptr is a pointer to an array of 4 characters, and when you index it you increment by that number of characters, which gets you to the next row of the string1 array.
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.
This question already has answers here:
Why canĀ“t we assign a new string to an char array, but to a pointer?
(4 answers)
Closed 9 years ago.
Why can't we do this in c:
char name[6];
name = "Jason";
However, with pointers we can.
char name;
char * pName = &name;
pName = "Jason";
What is the major difference between arrays and pointers ? I understand that the array is a fixed constant pointer, fair enough but I'm not quite sure about how this works if the name of an array is a pointer(pointer constant) which points to the first element in the array why can't I change the content of the elements of that array with an equal sign? I answered my question by saying it is a pointer constant but I don't grasp this concept!
Because when you write "a constant string", the compiler allocates this string in the compiled code and if you do c = "a string" where c is a pointer, c will now point to that particular location.
The position of an array instead is fixed (you cannot say "now point to something else"), so you should copy the string with strcpy.
strcpy(name, "Jason");
In this way the compiler will allocate "Jason" in the compiled code, but at execution time its content will be copied in the memory area dedicated to name.
Simply put, an array name is effectively a constant pointer to the array.
Since a constant object cannot be modified during execution, specifying an array as a lvalue i.e. to the left of an assignment operator is invalid.
To use your example, the following is the equivalent of trying to assigning something to a array name :
char name;
const char *pName = &name;
pName = "Jason"; //error!!
Checkout memcpy(), strcpy() to modify contents of an arrays. Take care to ensure that the arrays being written-to aren't constant (or statically allocated).
C never copies bare strings (the actual character data) around as a result of evaluating the = assignment operator. This is because such a thing is not considered "a value" in C. You can embed an array into a struct to make it a value, as pointed out in a comment.
Your first example would only make sense if it did, but it doesn't. The second example just assigns a pointer value, which is fine. But you cannot re-assign the address of an array (name is a constant pointer in the first example) so there's no way to make it work.
Also, remember that there are more arrays than character arrays, it would be weird to have that much special behavior overloaded on the = operator for character arrays, in my opinion.
I have seen in several pieces of code a string declared as char*. How does this work, surely it is a pointer to a single char, not an array of chars which makes up a string. If I wished to take string input to a method that would be called like this:
theMethod("This is a string literal");
What datatype should the parameter be?
surely it is a pointer to a single char, not an array of chars
It's a pointer to the first character of an array of char. One can access each element of the array using a pointer to its first element by performing pointer arithmetic and "array" indexing.
What datatype should the parameter be?
const char *, if you don't wish to modify the characters from within the function (this is the general case), and char * if you do.
This is a common beginner-C confusion. A pointer to any type, T *, is ambiguously either a pointer to a single object of type T, or a pointer to an element within a linear array of objects of type T, size unspecified. You, the programmer, are responsible for knowing which is which, and passing around length information as necessary. If you get it wrong, the compiler stands by and watches as your program drives off the undefined-behavior cliff.
To the extent C has strings (there is a strong case to be made that it doesn't really) they take shameless advantage of this ambiguity, such that when you see char * or const char * in a C program, it almost always will be a pointer to a string, not a single char. The same is not true of pointers to any other type.
per definition is "string" of type char * (or unsigned char * or const char *) however, it is a pointer to the first character of that character chain (i dont want to use the words array or vector). The Difference is to see in char: 'x' (single quote)
this is good old c programming (sometimes i could cry for loosing it)
char *p = "i am here";
for (q=p; ++q; *q) { // so lets start with p walk through and end wit the /0 after the last e
if (*q=='h') { // lets find the first 'h' and cut the string there
*(q-1)=0;
break;
}
}
i used no const and other probs here, i just try to clearify