I am writing a program which will store a list of file names as a string array. When I declare it as
char *filenames[1]
I have no errors... but when I do
char *filenames
I get a few errors. Not at the declaration but in later use. for example when I do:
filenames[3]= (char*)malloc( strlen(line) + 1);//here ERROR is : Cannot assign char* to char.
But with the first declaration with [1] it is all fine. I was just wondering what is the difference between them?
Trust me I tried looking for the answer on google but can't find any good ones regarding this case.
At the outset, char *filenames represents a char * variable named filenames whereas, char *filenames[1] represents an array of char * variables, with one element.
From the point of the usage, both are same, but the major difference is, the first one has to be used as a normal variable and the second one can be indexed, as an array.
If you're in need to use only one variable, don't use an array. You may be in danger of using out of bound indexes if you're not careful enough.
Also, as a note, please see this discussion on why not to cast the return value of malloc() and family in C..
Relative to this statement
filenames[3]= (char*)malloc( strlen(line) + 1);//here ERROR is : Cannot assign char* to char.
the both declarations are wrong.
The firwt declaration
char *filenames[1]
is wrong because it declares an array of pointers to char having only one element. But in the statement with memory allocation there is used index 3. So there is an attempt to access memory beyond the array becuase the only valid index for an array that has one element is 0.
The second declaration
char *filenames
is wrong because it does not declare an array of pointers. So applying the subscript operator for identifier filenames
filenames[3]
gives a scalar object of type char instead of a pointer of type char *
Related
I am not sure if this has been asked before. I tried my best to avoid duplicity.
I was using the sizeof() operator in C.
First I tried this:
char *name;
sizeof(name);
which returned size as 4 bytes. No issues till now.
Next time I tried this:
char name[];
sizeof(name); // I even tried name[]
which gave me a Compile error.
Anyone please explain why this occurs?
EDIT: I also tried inputting a string to *name which by far exceeded 4 bytes of length. Yet it was able to handle it properly. However the sizeof(name) still return 4 bytes. Even when the compiler has dynamically allocated enough memory to *name, it still reports occupying 4 bytes. Is this a sizeof() fault?
char name[]; at file scope is a tentative definition of an array. It has incomplete type. You do not know its size yet. You cannot do sizeof until after the definition has been completed.
Note that this has nothing to do with char *name; - arrays and pointers are different.
Re. your EDIT: you are confusing a pointer with the items being pointed to. char *name; takes up 4 bytes, and it points at another char. That is what a pointer does: it points at another object. It doesn't necessarily own what it points at. The semantics of a string is a series of char objects followed by a null terminator, and name should point at the first item of the series.
This all has nothing to do with sizeof name, which is the size of the pointer, not the size of the list of items being pointed at.
sizeof cannot be used with objects of incomplete array types.
char name[]; // name is of an incomplete type
C defines incomplete types as types that describe objects but lack
information needed to determine their sizes.
If you complete the type:
char name[];
char name[42]; // type of name is now completed
then using sizeof name would be valid.
Size of pointer to char is the space in memory required for that type of variable.
Size of an array of chars is number of chars in array. Which is undefined for non initialized array.
This question already has answers here:
Should I use char** argv or char* argv[]?
(10 answers)
Closed 8 years ago.
I've been fiddling around to see if there's any way to retain information about an array's length automatically when passed into a function (see my other question here: Why is this array size "workaround" giving me a warning?), but my question is more about a warning that gcc is giving that doesn't make sense to me.
According to this website (EDIT: I misread the website), char *p[10] declares a pointer to a 10-wide array of chars. But when I tried to pass in a pointer to an array into a function, I got this error message from the compiler:
Here is the rest of the program:
I know that when an array is passed into a function, it decays into a pointer (losing information about its length), but it seems that the declaration itself is decaying. What's going on here?
EDIT: When I replace the char *p[10] with char (*p)[10], it doesn't give the warning anymore, and more importantly, it displays the proper array length: 10. I guess my questions are 1) Why do the parentheses change things? and 2) Is this a well-known workaround or am I relying on some behavior of the compiler that isn't guaranteed? (i.e. that array length info can be passed by indirectly passing in a pointer to it?)
In fact char *p[10] is an array, of length 10, of pointers to char. You are looking for char (*p)[10]. That is a pointer to an array, of length 10, of char.
You might find http://cdecl.org/ a useful resource to help you test your understanding of declarations.
Regarding the discussion surrounding dynamic arrays, you are going to have to accept that once you allocate an array dynamically, the system provides no means for you to recover the length of the array. It is your responsibility to remember that information.
The subject of your question has been answered already but I wanted to address the heart of it, which is "can I encode the length of an array in its type?" Which is in fact what a pointer-to-array does. The real question is whether you can actually gain any brevity or safety from this. Consider that in each scope where you have a declaration of your type, the length still needs to be known a-priori. To show you what I mean let's generalize your example slightly by making 10 a compile-time constant N.
#define N 10
size_t arraylength(char (*arrayp)[N]) {
return sizeof(*arrayp);
}
int main(void) {
char array[N];
assert( arraylength(&array) == N ); //always true
}
So far so good. We didn't have to pass the length of array anywhere. But it's easy to see that anywhere the expression sizeof(*arrayp) is used, we also could have written N. And any place we declare a char(*)[ ], the bracketed length must come from somewhere.
So what if N isn't a compile time constant, and array is either a VLA or a pointer-to-array from malloc? We can still write and call arraysize, but it looks like this:
size_t arraylength(size_t N, char (*arrayp)[N]) {
return sizeof(*arrayp);
}
int main(void) {
size_t N = length_from_somewhere();
char array[N];
assert( arraylength(sizeof(array), &array) == N );
}
In defining arraysize N must still be visible before the declaration of arrayp. In either case, we can't avoid having N visible outside of the declaration of arrayp. In fact, we didn't gain anything over writing arraysize(size_t N, char* array) and passing array directly (which is a bit silly given the purpose of this function.) Both times arraylength could have equally been written return N;
Which isn't to say that array pointers are useless as parameters to functions -- in the opposite situation, when you want to enforce a length, they can provide type checking to make sure somefunc(char (*)[10]); receives a pointer to an array that is really (sans shady casting) 10 elements long, which is stronger than what a construct like [static 10] provides.
Also keep in mind that all of the length measurements above depend on the underlying type being char where length == size. For any larger type, taking the length requires the usual arithmetic e.g.
sizeof(*arrayp)/sizeof((*arrayp)[0])
In C, arrays decay to pointers to their first elements on most uses. In particular, what a function receives is always just a pointer to the first element, the size of the array is not passed with it.
Get a good text on C and read up on arrays.
I've been fiddling around to see if there's any way to retain information about an array's length automatically when passed into a function
The problem is so annoying that lots of programmers would love to have an answer. Unfortunately, this is not possible.
It seems that the declaration itself is decaying
Pointer to an array is not the same as a pointer to a pointer; that is why you are getting an error.
There is no decaying going on in your code, because you are not passing an array in your code sample: instead, you are trying to pass a pointer to an array &p. The pointer to an array of characters is not compatible to the expected type of the function, which is char**. Array size from the declaration is ignored.
You need to keep in mind two things:
1. Arrays are not pointers.
2. Array names decays to pointers (in most cases) when passed as arguments to functions.
So, when you declare
int a[10]; // a is an array of 10 ints
int *b; // b is a pointer to int
both of a and b are of different types. Former is of type int [10] while latter is of type int *.
In case of function parameter
void foo1 (int a[10]); // Actually you are not passing entire array
void foo2 (int a[]); // And that's why you can omit the first dimension.
void foo3 (int *a); // and the compiler interprets the above two third
ain all of the above function declarations is of same data type int *.
Now in your case
unsigned long arraySize(char *p[10]);
you can declare it as
unsigned long arraySize(char *p[]);
and hence
unsigned long arraySize(char **p);
All are equivalent.
char *p[10] char *p[] and char **p all are exactly equivalent but when they are declared as parameter of a function otherwise char *p[10] (an array of 10 pointers to char) and char **p (a pointer to pointer to char)are entirely of different type.
Suggested reading: C-FAQ: 6. Arrays and Pointers explains this in detailed.
Array name itself is a constant pointer. for example int arr[10]={0};
arr contains the address of arr[0]. hence arr equals&arr[0] .
when u pass the arraysize(&p) , you are actually passing a double pointer .
The correct format to pass a array pointer would be arraysize(&p[0]) or arraysizeof(p)
Note Array name is constant pointer , you cant change its value .
int arr[10];
arr++;
is invalid.
In your case you cant find a size of an array in function by passing the array name . it would return size of pointer(4 or 8 depends on your processor .
The method is to pass the size along with the array
func(array_name , array_size);
This is a general question about C.(I dont have a lot of experience coding in C)
So, if I have a function that takes a char* as an argument. How to know whether its a pointer to a single char or a char array, because if it's a char array I can expect a \0 but if it's not a char array then I wouldn't want to search for \0.
Is char* in argument a pointer to a single char or a char array?
Yes.
A parameter of type char* is always a pointer to a char object (or a null pointer, not pointing to anything, if that's what the caller passes as the corresponding argument).
It's not a pointer to an array (that would be, for example, a pointer of type char(*)[42]), but the usual way to access the elements of an array is via a pointer to the element type, not to the whole array. Why? Because an actual pointer-to-array must always specify the length of the array (42 in my example), which is inflexible and doesn't let the same function deal with arrays of different lengths.
A char* parameter can be treated just as a pointer to a single char object. For example, a function that gets a character of input might be declared like this:
bool get_next_char(char *c);
The idea here is that the function's result tells you whether it was successful; the actual input character is "returned" via the pointer. (This is a contrived example; <stdio.h> already has several functions that read characters from input, and they don't use this mechanism.)
Compare the strlen function, which computes the length of a string:
size_t strlen(const char *s);
s points to the first element of an array of char; internally, strlen uses that pointer to traverse the array, looking for the terminating '\0' character.
Ignoring the const, there's no real difference between the char* parameters for these two functions. In fact, C has no good way to distinguish between these cases: a pointer that simply points to a single object vs. a pointer that points to the first element of an array.
It does have a bad way to make that distinction. For example, strlen could be declared as:
size_t strlen(const char s[]);
But C doesn't really have parameters of array type at all. The parameter declaration const char s[] is "adjusted" to const char *s; it means exactly the same thing. You can even declare a length for something that looks like an array parameter:
void foo(char s[42]);
and it will be quietly ignored; the above really means exactly the same thing as:
void foo(char *s);
The [42] may have some documentation value, but a comment has the same value -- and the same significance as far as the compiler is concerned.
Any distinction between a pointer to a single object and a pointer to the first element of an array has to be made by the programmer, preferably in the documentation for the function.
Furthermore, this mechanism doesn't let the function know how long the array is. For char* pointers in particular, it's common to use the null character '\0' as a marker for the end of a string -- which means it's the callers responsibility to ensure that that marker is actually there. Otherwise, you can pass the length as a separate argument, probably of type size_t. Or you can use any other mechanism you like, as long as everything is done consistently.
... because if it's a char array I can expect a \0 ...
No, you can't, at least not necessarily. A char* could easily point to the first element of a char array that's not terminated by a '\0' character (i.e., that doesn't contain a string). You can impose such a requirement if you like. The standard library functions that operate on strings impose that requirement -- but they don't enforce it. For example, if you pass a pointer to an unterminated array to strlen, the behavior is undefined.
Recommended reading: Section 6 of the comp.lang.c FAQ.
You cannot determine how many bytes are referenced by a pointer. You need to keep track of this yourself.
It is possible that a char array is NOT terminated with a \0 in which case you need to know the length of the array. Also, it is possible for an array to have a length of 1, in which case you have one character with no terminating \0.
The nice thing about C is that you get to define the details about data structures, thus you are NOT limited to a char array always ending with \0.
Some of the terms used to describe C data structures are synonymous. For example, an array is sequential series of data elements, an array of characters is a string, and a string can be terminated with a null char (\0).
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Do these statements about pointers have the same effect?
All this time I thought that whenever I need to copy a string(either literal or in a variable) I need to use strcpy(). However I recently found out this:
char a[]="test";
and this
char *a="test";
From what I understand the second type is unsafe and will print garbage in some cases. Is that correct? What made me even more curious is why the following doesn't work:
char a[5];
a="test";
or this
char a[];
a="test";
but this works however
char *a;
a="test";
I would be greatful if someone could clear up things a bit.
char a[]="test";
This declares and initializes an array of size 5 with the contents of "test".
char *a="test";
This declares and initializes a pointer to the literal "test". Attempting to modify a literal through a is undefined behavior (and probably results in the garbage you are seeing). It's not unsafe, it just can't be modified since literals are immutable.
char a[5];
a="test";
This fails even when both a and "test" have the exact same type, just as any other attempt to copy arrays thorugh assignment.
char a[];
a="test";
This declares an array of unknown size. The declaration should be completed before being used.
char *a;
a="test";
This works just fine since "test" decays to a pointer to the literal's first element. Attempting to modify its contents is still undefined behavior.
Let's examine case by case:
char a[]="test";
This tells the compiler to allocate 5 bytes on the stack, put 't' 'e' 's' 't' and '\0' on it. Then the variable a points to where 't' was written and you have a pointer pointing to a valid location with 5 available spaces. (That is if you view a as a pointer. In truth, the compiler still treats a as a single custom type that consists of 5 chars. In an extreme case, you can imagine it something like struct { char a, b, c, d, e; } a;)
char *a="test";
"test" (which like I said is basically 't' 'e' 's' 't' and '\0') is stored somewhere in your program, say a "literal's area", and a is pointing to it. That area is not yours to modify but only to read. a by itself doesn't have any specific memory (I am not talking about the 4/8 bytes of pointer value).
char a[5];
a = "test";
You are telling the compiler to copy the contents of one string over to another one. This is not a simple operation. In the case of char a[] = "test"; it was rather simple because it was just 5 pushes on the stack. In this case however it is a loop that needs to copy 1 by 1.
Defining char a[];, well I don't think that's even possible, is it? You are asking for a to be an array of a size that would be determined when initialized. When there is no initialization, it's just doesn't make sense.
char *a;
a = "test";
You are defining a as a pointer to arrays of char. When you assign it to "test", a just points to it, it doesn't have any specific memory for it though, exactly like the case of char *a = "test";
Like I said, assigning arrays (whether null-terminated arrays of char (string) or any other array) is a non-trivial task that the compiler doesn't do for you, that is why you have functions for it.
Do not confuse assignment and initialisation in C, they are different.
In C a string is not a data type, it is a convention, utilising an array and a nul terminator. Like any array, when you assign it, it's name resolves as a mere pointer. You can assign a pointer, but that is not the same as assigning a string.
I want to know how an array of strings is declared? What I do is I declare an array of pointers of pointers to strings. Eg.
char *array[]= {"string1","string2","string3"};
I was reading about modifying environment variables in Linux and stumbled upon the pointer char **environ ( http://www.cs.bham.ac.uk/resources/courses/2005/17423/doc/libc/Environment-Access.html#Environment-Access ).
char **environ is declared as an array of strings. I think it should be a pointer to a pointer. For eg.
char *array[]= {"string1","string2","string3"};
environ = array;
Am I doing something wrong?
I also read somewhere that char *argv[] = char **argv. How is it possible?
Edit: I also found this thread to be very helpful.
Should I use char** argv or char* argv[] in C?
you are mixing up two different things that are in fact difficult to know for someone who is learning C. Declaration of variables inside a function and as a function parameter are not the same thing. The equivalence
char*argv[] ~~~ char **argv
holds because this a parameter (of main). There the array is in fact the same thing as declaring a pointer.
Your assignment environ = array is not wrong, syntactically, the compiler will accept it. But it is wrong semantically for several reasons:
You don't know who and how is
allocated *environ.
You loose the reference to the
initial contents of *eviron.
You assign a local storage that will
be recycled once you leave the scope
of the function. So *environ will
be undefined, once you left the
function.
So environ is a particularly bad example to do such an assignment.
well the problem is this. In your program are several pointer. One you asign to a array of strings and one called environ that points to the environment variables. What you say to C with environ = array is give environ the same value as array.. but array has a pointer to a local array. So after that statement the environ pointer will just point to the array you made but has not made any changes to its previous content.
I think you need to strcpy all elements of array to environ. Or use a api call setenv (i think it is)
and to you'r second question. Yes the first pair of [] can always be rewritten to a pointer. so array[] = *array as is array[][5] = (*array)[5] and there for *array[] = **array
i hope to have helped you.
In C a string is basically just an array of chars. in addition an array name also represents its address.
this is the reason why argv[] is the address of the array of chars (which is a string) and *argv is also the address of the string (since it's the address of the first char).