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.
Related
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Sizeof array through function in C [duplicate]
(2 answers)
Closed 4 months ago.
#include <stdio.h>
int avg(int []);
void main(){
int average;
int marks[5]={10,15,20,30,45};
printf("%d\n",sizeof(marks)); // answer is 20(as expected)
avg(marks);
}
int avg(int marks[]){
int sum=0;
printf("%d\n",sizeof(marks)); // answer is 8(why???)
}
In this code, I was trying to print the sizeof the integer pointer marks. When I print the sizeof the marks inside the main method it gives 20 as the result as we expected. But the same object passes to the avg function and prints the sizeof marks it shows the result as 8. I couldn't understand why that was happening.
Can anyone please clarify this?
Any help would be appreciated.
In the C programming language, arrays "decay" into pointers when passed to functions.
This means that in the scope where an array is declared, sizeof will be able to tell you how many bytes it takes up, but once it is passed to another function, sizeof can only tell you the size of a pointer to the type of the array. Effectively, when an array is passed as a parameter, you lose all length-of-array related information. All that is preserved is the memory-address where the array starts, and its type, so in your case, sizeof marks in main() is equivalent to sizeof(int[5]) and sizeof marks in avg() is equivalent to sizeof(int*).
The consequences of this are that if you are going to be passing arrays of different lengths to a function, then you either have to send a separate length parameter, or give the function some way to infer the length of the array.
For instance, C strings are implemented as arrays of char, such that the last character of the array is the null-terminator byte, '\0'. This allows a function that expects a C-standard string parameter to keep reading byte after byte from the string without stopping until it finds the '\0', but this is controversial, as it is a rather significant source of bugs and security concerns, because if this assumption fails, and there is no '\0' at the end of the string, then the function could very well blindly access memory it has no business messing with.
If you need to pass an array pointer to a function and preserve its length, the best (or perhaps least controversial) solution is to pass the length along with the array, so int avg(int marks[],int numMarks); might be a function prototype that will serve your purposes. You could implement a system, where there is a value of int that is an invalid mark to be averaged, and use it to mark the end of the array, but this is likely a more difficult solution to implement safely.
It is size of the int*, which is 8 on your system.
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.
This question already has answers here:
Difference between passing array and array pointer into function in C
(3 answers)
Closed 5 years ago.
As far as I know, you cannot modify a Array variable
How come this code run without any error.
Is there anything I am missing out here. (It's not about why there is 'L-VALUE REQUIRED' error , it's about why there isn't.)
#include<stdio.h>
int strlens(char *s);
void main(){
char s[]="get me length of this string ";
// s++ ; this would give 'L-VALUE REQUIRED ERROR'
printf("%d",strlens(s));
}
int strlens(char s[]){
int i;
for(i=0; *s!='\0';++i, ++s) ; //++s: there is NO 'L-VALUE REQUIRED ERROR'
return i;
}
A quirk of the C language that is well-known to seasoned C programmers, but trips up new C coders to no end, is that arrays are "pass by reference". Generally speaking, an array name used in most expressions will "decay" to the address of its first element. Functions carry that to an extreme case, where the array syntax in the function parameter is actually an alias for the pointer type itself.
This is described in paragraph 7 of c11's §6.7.6.3 Function declarators:
A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation.
Historically, this quirk was an attempt to maintain behavioral compatibility to C's predecessors, B and BCPL, and efficient structure layout. C's predecessor had a semantic for arrays in that its physical layout was actually a pointer that got dynamically allocated and initialized at runtime. When passed to a procedure, the pointer semantic was a natural adoption. Dennis Ritchie invented the notion of allowing the array syntax represent the actual address of the array, and then maintained the pointer semantic when passed to a function. Thus, the inventor of the C language considered this quirk a novel solution to a real world problem (semantic compatibility).
References:
The Development of the C Language
This line
char s[]="get me length of this string ";
defines a character array. s is not a pointer, it evaluates to an address (when fed to a pointer for instance, or when accessing a value like s[i] equivalent to *(s+i)), or represents the space occupied by the array (eg in sizeof(s))
But in a function signature like this
int strlens(char s[]){
char s[] is equivalent to char *s, and you can treat s like a pointer.
char arr[] = "asds"
Here, arr is just a name. It refers to a memory location but is not a pointer. The compiler substitutes the address directly wherever arr is used. It is not a pointer because unlike pointers, it does not have any space allocated to store an address. It is a mere compile time symbol. Hence, at run-time there is nothing on which you can do pointer arithmetic on. If you had to increment something, that something should exist at run-time.
More details:
Basically, the literal "asds" is stored in your executable and the compiler knows where exactly it is (well, the compiler is placing it in the executable, so it should know?).
The identifier arr is just a name to that location. As in, arr is not a pointer, i.e: it does not exist in memory storing an address.
void func(char arr[])
In case of a function argument, the arr does exist in memory at run-time because the arguments are pushed onto the call stack before making the function call. Since arrays are passed by reference, the address of the first element of the actual parameter is pushed onto the call stack.
Therefore, arr is allocated some space on the stack where it stores the address to the first element of your actual array.
Now you have a pointer. Hence you can increment (or do any pointer arithmetic on it).
This question already has answers here:
C pointer to array/array of pointers disambiguation
(13 answers)
what is difference between defining char a[5] and char (*a)[5]? [duplicate]
(4 answers)
Closed 8 years ago.
When I read books about C language, the two level pointer bothered me a lot.
char s[5][5];
char *s[5];
char (*s)[5];
so what is the difference between them?
In C, it is better to speak out the declaration. Then, it becomes intuitive. For this, you follow the right-left convention. Here is how it goes:
char *s[5];
How do you speak it? For that you start at the right of the variable name s and then go to the left. So you start by saying "s is a/an", On the right, you see a [] and you say "s is an array ... ". And then you go to the left and see the *, and say "s is an array of pointers." And that is what it is. It si an array of 5 pointers. You can store different pointers in this array.
Now for the other one:
char (*s)[5];
You start the same way. "s is a/an", and then look at the (). Anything within the () is bound to s closer than anything outside. So the * is more closely bound with s than []. So You now say, "s is a pointer ..." and now you go out of the parenthesis and see the []. So you continue, "s is a pointer to an array". And that is exactly what it is. It is a pointer, which will point to the first element of an array.
Now follow the same logic and try to guess what the following will be:
int (*callme)(int a, int b)
int (*callme[10])(int a, int b)
Hint, the last one can be used to create lookup tables for functions.
Edit:
As mentioned in the comments, there is also a char in the beginning. I have never ben able to figure out an easy way of speaking this, but is generally clear from the context. For example, in the first example, the char defines the type of the array, while in the second example, it defines pointer. In the exercises I have posted, the int defines the type for the return values of the functions. Generally with definitions such as these, there will be exactly one item with the undefined type. And thats how I figure out where the type goes.
first is 2 dimensional array of char
second is array of pointer to char
third is pointer to an array of char
While declaration was covered, perhaps differences in usage should also be pointed out:
char s[5][5]; --
s points to an area of allocated memory (heap if global, stack if local),
you may safely write up to 25 char values at s[0][0] .. s[4][4] (or at s[0] .. s[24]),
sizeof(s) == 25.
char *s[5]; --
s points to an area of allocated memory (heap if global, stack if local),
you may safely write up to 5 pointer values at s[0] .. s[4],
sizeof(s) == 40 (*).
char (*s)[5]; --
s does not point to any allocated memory -- it's merely an uninitialized pointer at this point,
you may safely write one pointer value at &s,
sizeof(s) == 8 (*).
(*) note: assuming a 64-bit architecture.
1.char s[5][5];
Here s is two dimensional array with 5 rows and 5 columns. Where in this 5 rows and 5 columns you will save element of type character.
2.char *s[5];
s is a one dimensional array with 5 elements each element is of type pointer to character.
3.char (*s)[5];
s is a pointer here not array. S points to a array of characters. for eg.
char arr[5][5];
char(*s)[5];
s = arr;
s[0][0] will be same as array of arr[0][0]
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.