Accessing arrays in an array of pointers - c

Let's say I have an array of pointers in C. For instance:
char** strings
Each pointers in the array points to a string of a different length.
If I will do, for example: strings + 2, will I get to the third string, although the lengths may differ?

Yes, you will (assuming that the array has been filled correctly). Imagine the double pointer situation as a table. You then have the following, where each string is at a completely different memory address. Please note that all addresses have been made up, and probably won't be real in any system.
strings[0] = 0x1000000
strings[1] = 0xF0;
...
strings[n] = 0x5607;
0x1000000 -> "Hello"
0xF0 -> "World"
Note here that none of the actual text is stored in the strings. The storage at those addresses will contain the actual text though.
For this reason, strings + 2 will add two to the strings pointer, which will yield strings[2], which will yield a memory address, which can then be used to access the string.

strings + 2 is the address of the 3rd element of the buffer pointed to by string.
*(strings + 2) or strings[2] is the 3rd element which is again a pointer to a buffer of characters.

i think you are looking to access third element through expression
strings[2];
but this will not be the case because look at the type of expression string[2]
Type is char *
As according to the standards
A 'n' element array of type 't' will be decayed into pointer of type __t__.With the exception when expression is an operand to '&' operator and 'sizeof' operator.
so strings[2] is equivalent to *(strings + 2) so it will print the contents of the pointer to pointer at third location,which is the contents of a pointer i.e an address.
But
strings+2;
whose type is char ** will print the 3 rd location's address,i.e,address of the 3rd element of array of pointer, whose base address is stored in **string.
But in your question you have not shown any assignment to the char ** strings and i am answering by assuming it to be initialised with particular array of pointers.
According to your question it is silly to do
*(strings + 2)
As it is not initialised.

Related

if array type does not have = operator then I understand that but why my casting of pointer/array to pointer to array is working not as expected

why this code does not seem to work the way I expect
char *c="hello";
char *x=malloc(sizeof(char)*5+1);
memcpy(x,(char(*)[2])c,sizeof("hello"));
printf("%s\n",x);
On this question I got comment you cannot cast a pointer to an array. But you can cast it to a pointer to array. Try (char*[2])c so I am just casting to pointer to array of two char so it will get first two characters from c becuase this is what (char(*)[2])c suppose to do. If not then am I missing anything? and I thought since Iam copying it the at index after 1 and 2 I get junk because i did not call memset. why I am getting full hello write with memcpy even though I just casted it t0 (char(*)[2])
how to extract specific range of characters from string with casting to array type-- What it can't be done?
Converting a pointer does not change the memory the pointer points to. Converting the c to char [2] or char (*)[2] will not separate two characters from c.
c is char * that points to the first character of "hello".
(char (*)[2]) c says to take that address and convert it to the type “pointer to an array of 2 char”. The result points to the same address as before; it just has a different type. (There are some technical C semantic issues involved in type conversions and aliasing, but I will not discuss those in this answer.)
memcpy(x,(char(*)[2])c,sizeof("hello")); passes that address to memcpy. Due to the declaration of memcpy, that address is automatically converted to const void *. So the type is irrelevant (barring the technical issues mentioned above); whether you pass the original c or the converted (char (*)[2]) c, the result is a const void * to the same address.
sizeof "hello" is 6, because "hello" creates an array that contains six characters, including the terminating null character. So memcpy copies six bytes from "hello" into x.
Then x[5]='\0'; is redundant because the null character is already there.
To copy n characters from position p in a string, use memcpy(x, c + p, n);. In this case, you will need to manually append a null character if it is not included in the n characters. You may also need to guard against going beyond the end of the string pointed to by c.

What is the use of "*&" in the code below

What is the use of *& in the printf statement and how is the output R?
#include <stdio.h>
int main() {
char* str = "ReplyCodeChallenge";
printf("%c\n", *&*str);
return 0;
}
and the output is: R
This is just a matter of multiple referencing and dereferencing.
str is a string pointer
*str is equivalent to *(str + 0) which is the same as str[0]
&(*str) denotes the address of str[0]
*(&*str) simply dereferences that address and gives str[0] back to you
The brackets don't matter here because both & and * fall under the same precedence group and their associativity is from right to left.
Since str[0] is 'R', that's your output.
By this example, you can conclude that *& or (*&*&...) makes no significant difference. But not always, you may see that syntax used in function headers to receive an argument of pointer-type through pass-by-reference mechanism.
char* str = "ReplyCodeChallenge"; defines str to be a pointer to char and initializes it to point to the first character of "ReplyCodeChallenge". ("ReplyCodeChallenge" is a string literal, which is effectively an array. In this use, it is automatically converted to a pointer to its first element, and that pointer is used as the initial value for str.)
str is a pointer to char, which points to the 'R'.
*str is that char, because * gives the thing that a pointer (an address) points to.
&*str is the address of that char, because & gives the address (a pointer) of a thing.
*&*str is that char, again because * gives the thing that a pointer points to.
There are already enough good answers but I add also mine -- like in any expression, you first of all need to split it in parsing tree, in order to detect the order of evaluation of subexpressions.
*&*str
Here you have 3 applications of 2 unary operators, each of them is
prefix unary-operator. So they have the same precedence, so the parsing tree is like that
(*(&(*str)))
The first application *(str) will return the first character from the beginning of str, which has the same address as str itself. So, &*str will be the address of str. So your applications will reduce to
*str
which is the 1st character (integer that represents the ASCII code) from string.
* - dereferences the object referenced by the pointer
& - gets reference to the object
char *p = "ABCD; - &*p, &*&*p, &*&*&*p, &*&*&*p... - does nothing, it is still reference stored in the pointer.
*&*p, *&*&*p, *&*&*&*p, *&*&*&*p... - just dereferences the char referenced by the pointer p, in this case 'A'
https://godbolt.org/z/ijffmP

Applying strcpy to a pointer to array + some_offset

This is a language-lawyer question.
The description of strcpy function is given at 7.24.2.3(p2):
The strcpy function copies the string pointed to by s2 (including
the terminating null character) into the array pointed to by s1.
So consider the following code:
char test[8] = "123";
strcpy(test + 3, "4567");
printf("%s\n", test); //1234567
It works as expected, but I'm confused about the object pointed to by test + 3. It is clear that object pointed to by test has declared type char[8]. But as far as I can see the Standard does not explicitly defined sort of this:
"If we have an array of n elements than a pointer to i < nth element can be considered a pointer to the first element of an array of n - i elements".
Since the function strcpy requires its first operand to be an array can we pedantically speaking apply pointer arithmetic as I showed above?
Of course s1 does not point to an array, it points to a char. But the term usage comes from the 7.1.4p1:
[...] If a function argument is described as being an array, the pointer actually passed to the function shall have a value such that all address computations and accesses to objects (that would be valid if the pointer did point to the first element of such an array) are in fact valid. [...]
For strcpy(test + 3, "4567"); the accesses test[3 + 0 ... 4] shall be valid, which is the case, among others possibilities, if test is an array of at least 8 characters.
Yes, because even though the semantics of the function strcpy only make sense when dealing with arrays instead of pointers, there is no way for strcpy (or any other function) to tell whether it was passed an array or a pointer to an array, since when an array is passed as an argument to a function, it decays to a pointer to its first element.

Differences between arrays, pointers and strings in C

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];

question regarding pointer in c language

char *sample = "String Value";
&sample is a pointer to the pointer of "String Value"
is the above statement right?
If the above statement right, what is the equivalent of &sample if my declaration is
char sample[] = "String Value"
In the first one, there are two objects being created.
One is a char * (pointer-to-char) called sample, and the other is an unnamed array of 13 chars containing the characters of the string. In this case, &sample gives the address of the object sample, which is the address of a pointer-to-char - so, a pointer-to-pointer-to-char.
In the second example, there's only one object being created; an array of 13 chars called sample, initialised with the characters of the string. In this case, &sample gives the address of the object sample - so, a pointer-to-array-of-13-chars.
In the second example, there is no "equivalent" to &sample in the first example, in the sense of a pointer-to-pointer-to-char value. This is because there is no pointer-to-char value to take the address of. There is only the array.
While pointers provide enormous power and flexibility to the programmers, they may use cause manufactures if it not properly handled. Consider the following precaustions using pointers to prevent errors. We should make sure that we know where each pointer is pointing in a program. Here are some general observations and common errors that might be useful to remember. *ptr++, *p[],(ptr).member
In the first part &sample will return the address of 'sample' pointer created and in the second case the starting address of the string created as object.
In C arrays and pointers are more or less interchangable. You can treat an array name like it is a pointer, and a pointer like it is an array name.
If you take the address of (&) of a pointer, of course you get a pointer to a pointer.
&sample is the address of the pointer that points to "String Value".
For the second example, since an array name that is not followed by a subscript is interpreted as the pointer to the initial element of the array, which means
sample
and
&sample[0]
are the same, therefore &sample is also the address of the pointer that points to the string.

Resources