char (*ptr)[10];
scanf("%s",ptr);//inputing a string
Why is this not working?
According to me this should work because ptr is a pointer to an array of characters.
A pointer to an array is NOT an array, you have nowhere to put your characters.
It's like having a doormat without a house, that doesn't mean you have somewhere to receive your guests.
To have the above working you should
char ptr[10]; // This is where you have space, specifically stack space
char (*this_is_a_pointer_to_array)[10]; // This only holds space to keep an address to an array
this_is_a_pointer_to_array = &ptr;
scanf("%s",ptr);
although you don't really need the pointer to array in the case above.
A pointer to an array only holds as much space as necessary to hold the address to an array, there's no space to store anything else than an address. If you horribly circumvent the typecasting mechanism you might use that space to store some characters instead of an address, but that is against every moral fiber of my body and probably against every typecasting rule as well.
ptr is not a pointer to char instead it is a pointer to an array of 10 chars.
Related
I'm trying to make a small text editor and efficient (space/time wise). I also want to save changes to the text; I would save changes and the main text in two lists, both made of nodes like this:
struct node{
int startingLine;
int endingLine;
char *line;
char *newLine;
};
My idea is to use this struct both for the text list and the changes list;line and newLine are to point at char arrays (the lines of text)
when these are text nodes the newLine array is empty or points at null, and when the line gets changed this node is just moved to the changes list and the newLine array gets filled with the new line that replaced the first in the text;
this way I would not have to free the node from the text list and malloc another node in the changes list and also copy all the information; but:
when I try to set an array to NULL i get an error; I wonder why, I thought array names were just pointers?
also, to use the heap I only know malloc(sizeof(struct node)), does it allocate space for the second pointer too even if i don't immediately need it?
So in conclusion I ask if this is a good idea or how to work around it or if it can be polished somehow; maybe immediately after allocating a node I should set newLine to NULL? A NULL pointer occupies no memory at all or still something compared to not putting any pointer in the struct? Because as is said the idea would be to have the text list made of nodes but with all their "useless" newLine pointers hanging there.
when I try to set an array to NULL i get an error; I wonder why, I thought array names were just pointers?
No. An array variable is similar to a pointer, and convertible to a pointer, but it's a different type. See Is an array name a pointer? for a more complete answer on this.
also, to use the heap I only know malloc(sizeof(struct node)), does it allocate space for the second pointer too even if i don't immediately need it?
When you allocate a node, the second pointer is part of that structure, so the pointer itself exists. But malloc() has no idea what the pointers in your node should point to, and it doesn't allocate the memory that line and newLine point to.
I ask if this is a good idea or how to work around it or if it can be polished somehow; maybe immediately after allocating a node I should set newLine to NULL?
If the fields in your node structure are what you need, then it's fine. Setting line and newLine to nil when you create a new node is a good idea so that you won't accidentally dereference a garbage pointer.
A NULL pointer occupies no memory at all or still something compared to not putting any pointer in the struct?
The pointers themselves are part of the node struct, so the take up as much memory as any two pointers. The things that line and newLine point to use as much memory as they need. If line and newLine are nil, then they don't point to anything and of course no memory is used. You could have a thousand pointers all pointing to the same block of memory, and the space needed would be still just the size of that block and the space occupied by the pointers themselves. Try to distinguish between a pointer, which is just an address, and the data at that address; they're completely different things.
So about efficiency, this can be good to avoid creating new nodes and copying in all the data, because just allocating the pointer itself takes very little space i hope?
Yes, a pointer typically takes only 8 bytes on a 64-bit system, so not a lot. But you still have to allocate space for the actual data, so it's not obvious that your approach will be more efficient with respect to space than other methods.
It can be tough to get the hang of pointers at first. The best way to get it is to spend a lot of time with pointers. I'd suggest that you do some exercises to practice, e.g. create a program that breaks some input text into a linked list of words and then sorts the list. To attempt writing a text editor that manipulates blocks of data when your understanding of pointers is shaky is to set yourself up for a world of hurt; time that you spend building your confidence with pointers will pay for itself a hundred times over.
when I try to set an array to NULL i get an error; I wonder why, I thought array names were just pointers?
No. Unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T" and the value of the expression will be the address of the first element of the array. Otherwise, arrays and pointers are completely different animals.
When you declare an array like
int a[10];
what you get in memory is
+---+
| | a[0]
+---+
| | a[1]
+---+
...
+---+
| | a[9]
+---+
That's it. There's no separate pointer object storing the address of the first element. There's no a object separate from the array elements themselves. It's just a sequence of elements. During translation, any instance of the expression a that's not an operand of sizeof or unary & will be replaced with the address of a[0].
also, to use the heap I only know malloc(sizeof(struct node)), does it allocate space for the second pointer too even if i don't immediately need it?
It will allocate space for the line and newLine pointer members, yes; it won't allocate any additional memory for them to point to. That would have to be done as a separate step, e.g.
struct node *n = malloc( sizeof *n );
if ( n )
{
n->line = malloc( line_length + 1 ); // sizeof (char) is 1 by definition so we don't need a sizeof here, +1 to account for string terminator;
...
}
This means you'll have to call free( n->line ) before calling free( n ).
A NULL pointer occupies no memory at all or still something compared to not putting any pointer in the struct?
A pointer object takes up the same amount of space regardless of whether its value is NULL or not. It's like an int takes up the same amount of space whether it's value is 0, 1, 65535, or 2147483647.
The exact size of a pointer type depends on the platform and the pointer type itself. C does not require a specific size for pointer types, nor does it require all pointer types to be the same size. The only requirements are
void * and char * have the same size and alignment;
pointers to qualified types have the same size and alignment as their unqualified equivalent (i.e., const int * and volatile int * and int * should all have the same size);
pointers to all struct types have the same size and alignment;
pointers to all union types have the same size and alignment;
On most modern, general-purpose platforms like x86 and x86-64, all pointer types will have the same size. That may not be the case on some embedded or special-purpose architectures, though.
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.
Just have a question in mind that troubles me.
I know pointers and arrays are different in C because pointers store an address while arrays store 'real' values.
But I'm getting confused when it comes to string.
char *string = "String";
I read that this line does several things :
An array of chars is created by the compiler and it has the value String.
Then, this array is considered as a pointer and the program assigns to the pointer string a pointer which points to the first element of the array created by the compiler.
This means, arrays are considered as pointers.
So, is this conclusion true or false and why ?
If false, what are then the differences between pointers and arrays ?
Thanks.
A pointer contains the address of an object (or is a null pointer that doesn't point to any object). A pointer has a specific type that indicates the type of object it can point to.
An array is a contiguous ordered sequence of elements; each element is an object, and all the elements of an array are of the same type.
A string is defined as "a contiguous sequence of characters terminated by and including the first null character". C has no string type. A string is a data layout, not a data type.
The relationship between arrays and pointers can be confusing. The best explanation I know of is given by section 6 of the comp.lang.c FAQ. The most important thing to remember is that arrays are not pointers.
Arrays are in a sense "second-class citizens" in C and C++. They cannot be assigned, passed as function arguments, or compared for equality. Code that manipulates arrays usually does so using pointers to the individual elements of the arrays, with some explicit mechanism to specify how long the array is.
A major source of confusion is the fact that an expression of array type (such as the name of an array object) is implicitly converted to a pointer value in most contexts. The converted pointer points to the initial (zeroth) element of the array. This conversion does not happen if the array is either:
The operand of sizeof (sizeof array_object yields the size of the array, not the size of a pointer);
The operand of unary & (&array_object yields the address of the array object as a whole); or
A string literal in an initializer used to initialize an array object.
char *string = "String";
To avoid confusion, I'm going to make a few changes in your example:
const char *ptr = "hello";
The string literal "hello" creates an anonymous object of type char[6] (in C) or const char[6] (in C++), containing the characters { 'h', 'e', 'l', 'l', 'o', '\0' }.
Evaluation of that expression, in this context, yields a pointer to the initial character of that array. This is a pointer value; there is no implicitly created pointer object. That pointer value is used to initialize the pointer object ptr.
At no time is an array "treated as" a pointer. An array expression is converted to a pointer type.
Another source of confusion is that function parameters that appear to be of array type are actually of pointer type; the type is adjusted at compile time. For example, this:
void func(char param[10]);
really means:
void func(char *param);
The 10 is silently ignored. So you can write something like this:
void print_string(char s[]) {
printf("The string is \"%s\"\n", s);
}
// ...
print_string("hello");
This looks like just manipulating arrays, but in fact the array "hello" is converted to a pointer, and that pointer is what's passed to the print_string function.
So, is this conclusion true or false and why ?
Your conclusion is false.
Arrays and pointers are different. comp.lang.c FAQ list ยท Question 6.8 explains the difference between arrays and pointers:
An array is a single, preallocated chunk of contiguous elements (all of the same type), fixed in size and location. A pointer is a reference to any data element (of a particular type) anywhere. A pointer must be assigned to point to space allocated elsewhere, but it can be reassigned (and the space, if derived from malloc, can be resized) at any time. A pointer can point to an array, and can simulate (along with malloc) a dynamically allocated array, but a pointer is a much more general data structure.
When you do
char *string = "String";
and when a C compiler encounters this, it sets aside 7 bytes of memory for the string literal String. Then set the pointer string to point to the starting location of the allocated memory.
When you declare
char string[] = "String";
and when a C compiler encounters this, it sets aside 7 bytes of memory for the string literal String. Then gives the name of that memory location, i.e. the first byte, string.
So,
In first case string is a pointer variable and in second case it is an array name.
The characters stored in first case can't be modified while in array version it can be modified.
This means arrays is not considered as pointers in C but they are closely related in the sense that pointer arithmetic and array indexing are equivalent in C, pointers and arrays are different.
You have to understand what is happening in memory here.
A string is a contiguous block of memory cells that terminates with a special value (a null terminator). If you know the start of this block of memory, and you know where it ends (either by being told the number of memory cells or by reading them until you get to the null) then you're good to go.
A pointer is nothing more than the start of the memory block, its the address of the first memory cell, or its a pointer to the first element. All those terms mean the same thing. Its like a cell reference in a spreadsheet, if you have a huge grid you can tell a particular cell by its X-Y co-ordinates, so cell B5 tells you of a particular cell. In computer terms (rather than spreadsheets) memory is really a very, very long list of cells, a 1-dimensional spreadsheet if you like, and the cell reference will look like 0x12345678 rather than B5.
The last bit is understanding that a computer program is a block of data that is loader by the OS into memory, the compiler will have figured out the location of the string relative to the start of the program, so you automatically know which block of memory it is located in.
This is exactly the same as allocating a block of memory on the heap (its just another part of the huge memory space) or the stack (again, a chunk of memory reserved for local allocations). You have the address of the first memory location where your string lives.
So
char* mystring = "string";
char mystring[7];
copy_some_memory(mystring, "string", 7);
and
char* mystring = new char(7);
copy_some_memory(mystring, "string", 7);
are all the same thing. mystring is the memory location of the first byte, that contains the value 's'. The language may make them look different, but that's just syntax. So an array is a pointer, its just that the language makes it look different, and you can operate on it with slightly different syntax designed to make operations on it safer.
(note: the big difference between the 1st and other examples is that the compiler-set set of data is read-only. If you could change that string data, you could change your program code, as it too it just a block of CPU instructions stored in a section of memory reserved for program data. For security reasons, these special blocks of memory are restricted to you).
Here's another way to look at them:
First, memory is some place you can store data.
Second, an address is the location of some memory. The memory referred to by the address may or may not exist. You can't put anything in an address, only at an address - you can only store data in the memory the address refers to.
An array is contiguous location in memory - it's a series of memory locations of a specific type. It exists, and can have real data put into it. Like any actual location in memory, it has an address.
A pointer contains an address. That address can come from anywhere.
A string is a NUL-terminated array of characters.
Look at it this way:
memory - A house. You can put things in it. The house has an address.
array - A row of houses, one next to the other, all the same.
pointer - a piece of paper you can write an address on. You can't store anything in the piece of paper itself (other than an address), but you can put things into the house at the address you write on the paper.
We can create an array with the name 'string'
char string[] = "Hello";
We can allocate a pointer to that string
char* stringPtr = string;
The array name is converted to a pointer
So, an array name is similar to the pointer. However, they're not the same, as the array is a contiguous block of memory, whereas the pointer references just a single location (address) in memory.
char *string = "String";
This declaration creates the array and sets the address of the pointer to the block of memory used to store the array.
This means, arrays are considered as pointers. So, is this conclusion true or false
False, arrays are not pointers. However, just to confuse(!), pointers can appear to be arrays, due to the dereference operator []
char *string = "String";
char letter = string[2];
In this case string[2], string is first converted to a pointer to the first character of the array and using pointer arithmetic, the relevant item is returned.
Then, this array is considered as a pointer and the program assigns to the pointer string a pointer which points to the first element of the array created by the compiler.
Not really great wording here. Array is still an array and is considered as such. The program assigns a pointer-to-first-element value (rvalue) to pointer-to-char variable (lvalue in general). That is the only intermediate/non-stored pointer value here, as compiler and linker know array's address at compile-link time. You can't directly access the array though, because it is anonymous literal. If you were instead initializing an array with literal, then literal would disappear (think like optimized-out as separate entity) and array would be directly accessible by its precomputed address.
char s[] = "String"; // char[7]
char *p = s;
char *p = &s[0];
I am wondering if there is a difference between doing this
char ** str;
str=(char **)malloc(sizeof(char*) * ARRAY_LEN);
and doing this :
str=(char*)malloc(sizeof(char)* ARRAY_LEN);
for(i=0;i<ARRAY_LEN;i++)
*(str+i)=(char*)malloc(sizeof(char)* ARRAY_LEN);
and doing this is the same too :
char str[ARRAY_LEN][ARRAY_LEN];
Yes, one is a pointer to a pointer to char, and the other is a pointer to char, there is a very big difference. between those. You can think of it as an array of strings in the first case, and a single string in the second.
Of course, in the first case you have to somehow allocate memory for the actual strings in the "array".
It all depends on what you want to achieve. I guess it is an array of strings, but maybe neither of your snippets will perform what you want. So let's go over them:
char ** str;
str=(char **)malloc(sizeof(char*) * ARRAY_LEN);
str is a pointer to a pointer to char. This could indeed be used for that purpose. The malloc then properly allocates space for ARRAY_LEN number of pointers to char, also OK for the intended purpose. The problem may lie in that there are no actual strings allocated, that is, all the ARRAY_LEN pointers to char are left pointing to God knows where (malloc() does not initialize them, not even to NULL). One way to properly finish this up would be setting all the pointers to NULL indicating your string list is empty.
str=(char*)malloc(sizeof(char)* ARRAY_LEN);
for(i=0;i<ARRAY_LEN;i++)
*(str+i)=(char*)malloc(sizeof(char)* ARRAY_LEN);
I assume str is still a pointer to a pointer to char. Then the cast itself will be invalid, as well as occupying just ARRAY_LEN bytes (sizeof(char) evaulates to 1) for ARRAY_LEN number of pointers (well, undefined as soon as you try to access all those...). The second part, the for loop would be OK for completing the first scenario if you wanted a rectangular array of chars, but this case the assignment to *(str+i) will likely cause a segfault when the loop starts writing outside the insufficient storage allocated for str.
char str[ARRAY_LEN][ARRAY_LEN];
This is a plain rectangular 2 dimensional array of chars. Note that it is conceptually different from both of the above! str can't decay to have an equal meaning to char ** str above since it's 2 dimensional (one dimensional arrays may decay to pointers as needed).
In all three cases it seemed you tried to get a rectangular (ARRAY_LEN * ARRAY_LEN) storage of characters, in the first two in the form of double indirection, in the last as a 2 dimensional array. This might not be what you wanted to do, probably you rather wanted to get an array of strings. If you don't know anything about the strings in advance, and neither their maximum length, this is more complicated to perform properly (you might want to handle all strings separately, by some means depending on use case figuring out their length, and allocating accordingly - probably even needing coding dynamically growing storage). Otherwise if you know or can limit the maximum length (pay attention to a terminating zero), you may allocate accordingly, and then limit the string lengths while you read them in.
Hope it helps.
How can I get the address of a multidimensional static array?
For example, this is my array
char array[2][10] = {"word1", "word2"};
Is it possible to get the address to make me reference this array using a pointer like this?
char** pointer;
I tried &array or directly pointer = (char**)array; but it crashes at startup.
char **pointer means that a pointer is pointing to a pointer.
So *pointer is expected to be a pointer (e.g. 4-byte value which can be interpreted as an address).
This is not the case with your array: it is a contiguous area in memory (20 bytes).
So when you try to convert the array to char ** your application crashes.
It's not possible to do this conversion, char ** must point at a pointer.
"array" is the address of the array in memory but it is not a char**. While you can cast it, the application will crash if you try
printf("%s", pointer[1]);
because in your case is probably the same as
printf("%s", (char *)(0x00000031));
since pointer[1] means "the second 4 byte pointer (assuming x86) starting from 'array'".
pointer[0] MAY not crash but won't show "word1" either for the same reason.
You probably want (this is hard to remeber so i had to check online, hope it is correct):
char (*pointer)[10] = array;
Which is a pointer to an array of 10 chars. And if you use pointer[1] it now means "the second 10 chars block starting from 'array'".