memset on static array - c++

I am a little confused about what to pass as the first parameter to memset when you have to set the elements of a static array. I've been searching but I couldn't find the answers to some specific questions I have.
If I have an array declared as:
char arr[10];
I have seen that these two calls are valid and produce the same effect:
memset( arr, 0, 10);
memset( &arr, 0, 10);
My specific questions are:
1- Why do they have the same effect on arr?
2- What is the different between these calls?
3- Which one would be considered the correct one?
Thank you!

Storage duration has nothing to do with it; an array is an array. This expression:
&arr
produces a char (*)[10], i.e., a pointer to an array of char with 10 elements. However, when arr is passed to a function like so:
memset(arr, 0, 10);
it degrades to a pointer to the first element, i.e., a char*. These are not the same thing. The "correct" (idiomatic) call is:
memset(arr, 0, 10);
However, in this case they are both converted to a void* when passed to memset and interpreted in the function as an unsigned char*. Since they both point to the same place it produces the same result.
However, it is important to realize that, when dealing with the true respective types (i.e., not a void*), a pointer to an array is not the same as a pointer to the first element of an array.
For example, incrementing a char (*)[10] will increment the pointer sizeof(char[10]) bytes, while incrementing a char* will increment only one byte.

Why do they have the same effect on arr? What is the different between these calls?
Because the address of an array is the same as the address of its first element (arrays decay into pointers to their first element when passed to a function), it's just that they have a different type. arr has type char[10], that decays into char * when passed to a function. In contrast, &arr has the type char (*)[10] which doesn't change when passed as a function argument.
Which one would be considered the correct one?
As long as the function doesn't expect a specific type, i. e. it accepts void *, either one is good. If the called function, however, expects that either of the types be specified, then the other one should not be used, since then your program would be malformed and invoke undefined behavior.

1- Why do they have the same effect on arr?
They both contain the same value which is the address of the beginning of the array.
2- What is the different between these calls?
arr decays to a pointer to char, i.e. char* (this conversion happens when you pass the name of an array to a function) and &arr is a pointer to an array of char, i.e. char (*)[].
3- Which one would be considered the correct one?
I would use arr. memset accepts a void* which is the reason both work.
Also, note that char arr[10] = {}; can be used to zero initialize the array.

Related

Why don't I have to give the function the address of the array

Hi I'm new to C and learning about pointers. I'm writing a simple recursive function to test it where it takes parameters int *a and int size. In my main method, I send print_array the address of the first character of my array using the & beforehand.
This doesn't seem to work, I get given an "incompatible pointer types" error at compilation. I understand that I can remove the & and the program works fine. I have a question:
Why can't I pass in the memory address of my_array from main with a &? Shouldn't I be able to just give the function the memory address of first element of array and it can deal with the rest?
Thanks, hope this question wasn't too noob.
#include <stdio.h>
#include <stdlib.h>
void print_array(int *a, int size){
if (size>0){
printf("%d\n", a[0]);
print_array(a+1, size-1);
}
}
int main(void){
int my_array[20];
int i;
for (i=0; i < 20; i++){
my_array[i] = rand() % 20;
}
/*the contents of the array*/
printf("The contents of the array\n");
for (i=0; i < 20; i++){
printf("%d\n", my_array[i]);
}
printf("The recursive method print\n");
print_array(&my_array, 20);
return EXIT_SUCCESS;
}
Yes, you can give the function the address of the first element, and let it deal with the rest. You could do that as either:
print_array(my_array, 20);
...or:
print_array(&my_array[0], 20);
Unfortunately, while &my_array is legal code, it produces a pointer to the entire array, rather than a pointer to the first element of the array. Those have the same address, but different types, which is what's causing the error.
The type of a pointer determines (among other things) how arithmetic on that pointer will work. In your case, print_array prints the first int in the array, then adds one to the pointer. Since it's a pointer to int, that addition actually adds the size of an int to the address in the pointer.
If you used a pointer to the entire array, then adding one would instead add the size of the entire array to the address. For example, let's assume 4-byte ints and that my_array has a base address of 1000. In this case, my_array+1 will yield 1004, so it holds the address of the second int in the array (just as you undoubtedly wanted). By contrast, &my_array will take the address of the entire array, with the type "pointer to array of 20 ints". When you add one to it, that will add 1 * the size of the pointed-to type to the address, so you'll get 1080 (i.e., the entire array is 20 * 4 = 80 bytes). This is obviously not what you wanted--instead of x+1 pointing to the second item in the array, it now points past the end of the array, and attempting to dereference the pointer will give undefined behavior.
So, just switch to one of the forms above (my_array or &my_array[0]). As a more general point, realize that the name of an array evaluates as a pointer to the first element of the array under most circumstances--the notable exceptions being when you use the name of the array as a the operand of either the sizeof operator or the address-of operator (as you did here). In these two cases, the name of the array still refers to the entire array instead of a pointer to the first element.
Your function needs a pointer to an int, specifically the address of the first (0th) element of the array.
By calling print_array(&my_array, 20);, you're trying to pass the address of the entire array, a value of type int(*)[20], which is different than int*. It points to the same memory location, but it's of a different type.
To pass the address of the first element, you can write:
print_array(&my_array[0], 20);
or, equivalently:
print_array(my_array, 20);
The latter works because, in most but not all contexts, the name of an array is implicitly converted to a pointer to its first element.
The relationship between arrays and pointers in C and C++ can be confusing. Recommended reading: Section 6 of the comp.lang.c FAQ
Because arrays automatically decay to pointers, the following was extracted from the n1570 draft
6.3.2 Other operands
6.3.2.1 Lvalues, arrays, and function designators
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. If the array object has
register storage class, the behavior is undefined.

How to use strtof endPointer?

Looking at the examples presented by various google results, I don't really understand how the EndPtr works. For an example:
char szOrbits[] = "686.97 365.24";
char* pEnd;
float f1 = strtof (szOrbits, &pEnd);
The function takes the pointer of the pointer that is declared after the char array, does that mean that the actual type and contents of the pointer are irrelevant and the pointer is guaranteed to be allocated right after the array thus making its address the end point?
I tried using it like this:
ret.push_back(EquationPiece(strtof(&Source[mark], (char**)&Source[i])));
where ret is a vector, Source is a char array, mark is where the number begins and i is the next byte after the number but I'm getting some strange results. Is my usage incorrect or should I seek for the bug elsewhere?
Although the reference page describes the parameter pendptr as a reference to a char* object this might be misundestood. In C we have only pointers and the second parameter of strtof is a pointer to a pointer to char.
You can utilize this parameter to get the point in the input char array that could not be used to convert the char array to the output float. If the pointer points to a '\0' than the array has been converted entirely. If it points to something different you can start error handling or further processing of the char array.
You should never cast any pointer when you are not sure what it means. Cast tells the compiler that the programmer knows it better. Depending on the meaning of your EquationPiece it might be useful to pass the endPtr:
ret.push_back(EquationPiece(strtof(&Source[mark], pEnd));

In C/C++, for an array a, I just learned that (void*)&a == (void*)a. How does that work?

So, I always knew that the array "objects" that are passed around in C/C++ just contained the address of the first object in the array.
How can the pointer to the array "object" and it's contained value be the same?
Could someone point me towards more information maybe about how all that works in assembly, maybe.
Short answer: A pointer to an array is defined to have the same value as a pointer to the first element of the array. That's how arrays in C and C++ work.
Pedantic answer:
C and C++ have rvalue and lvalue expressions. An lvalue is something to which the & operator may be applied. They also have implicit conversions. An object may be converted to another type before being used. (For example, if you call sqrt( 9 ) then 9 is converted to double because sqrt( int ) is not defined.)
An lvalue of array type implicitly converts to a pointer. The implicit conversion changes array to &array[0]. This may also be written out explicitly as static_cast< int * >( array ), in C++.
Doing that is OK. Casting to void* is another story. void* is a bit ugly. And casting with the parentheses as (void*)array is also ugly. So please, avoid (void*) a in actual code.
You are mixing two unrelated (and, actually, mutually exclusive) things, which creates more confusion.
Firstly, you are correctly stating that "array objects that are passed around in C/C++ just contained the address of the first object in the array". The key words here are "passed around". In reality arrays cannot be passed around as array objects. Arrays are not copyable. Whenever you are using an array-style declaration in function parameter list it is actually interpreted as pointer declaration, i.e. it is a pointer that you are "passing around", not the array. However, in such situations your equality does not hold
void foo(int a[]) {
assert((void *) &a == (void *) a); // FAIL!!!
}
The above assertion is guaranteed to fail - the equality does not hold. So, within the context of this question you have to forget about arrays that you "pass around" (at least for the syntax used in the above example). Your equality does not hold for arrays that have been replaced by pointer objects.
Secondly, actual array objects are not pointers. And there's no need to take the term object into quotation markes. Arrays are full-fledged objects, albeit with some peculiar properties. The equality in question does indeed hold for the actual arrays that have not lost their "arrayness", i.e. array object that have not been replaced by pointer objects. For example
int a[10];
assert((void *) &a == (void *) a); // Never fails
What it means is that numerically the address of the entire array is the same as the address of its first element. Nothing unusual here. In fact, the very same (in nature) equality can be observed with struct types in C/C++
struct S { int x; } a;
assert((void *) &a == (void *) &a.x); // Never fails
I.e. the address of the entire struct object is the same as the address of its first field.
How can the pointer to the array "object" and it's contained value be the same?
An array is a contiguous block of memory which stores several elements.
Obviously, the first element in the array is located at some address.
There's no data "in between" the first element and the beginning of the actual array.
Therefore, the first element has the same address as the array.
Please read the following thread
http://www.cplusplus.com/forum/beginner/29595/
It basically explains that (&a != a) due to the type difference (since &a returns the pointer to the array and a to the first element) even though they both point to the same address.
Since you are casting them both to (void*) only the address value is compared and found to be equal, meaning that ((void*) a == (void*)&a) as you've stated. This makes sense since the array's address has to be the same as the first elements.
Let's look at these two declarations:
int a[4];
int * b;
Both a and b have a type compatible with int * and can, for example, be passed as an argument to a function expecting int *:
void f(int * p);
f(a); // OK
f(b); // OK
In case of a, the compiler allocates space for 4 int values. When you use the name a, such as when calling f(a), the compiler just substitutes the address of where it allocated the first of those int values, since it knows.
In case of b, the compiler allocates space for one pointer. When you use the name b, such as when calling f(b), the compiler generates code for retrieveing the pointer value from the allocated storage.
When it comes to &, that's when the difference between a and b becomes apparent. & always means the address of the storage the compiler has allocated for your variable: &a is the address of those four int values (therefore coinciding with just a), while &b is the address of the pointer value. They have different types, too.
&a is not exactly the same as a, though, even though they compare as equal. They have a different type: &a is a pointer and a is an array. You can notice the difference, for example, if you apply the sizeof operator to these expressions: sizeof(a) will evaluate to the size of four int values, while sizeof(&a) is the size of a pointer.
Ok, So what I thought happened is that when you created an array, you allocated space for the array somewhere and you created a pointer to its first object somewhere else, and what you passed around in your code was the pointer.
This is actually the behavior of what happens when you create an array with new in C++ or with malloc in C/C++. As such,
int * a = new a[SIZE];
assert((void*)&a==(void*)a); // Always fails
What I learned is that for arrays declared in the style of int a[SIZE];, a pointer to the first element is created when you try to pass the array to a function (this is called array-pointer decay). It's interesting to note that, indeed, as AndreyT writes,
void foo(int a[]) {
assert((void *) &a == (void *) a); // Always fails
}
This shows that it's only when you try to pass arrays around that a pointer is created for arrays in the style of int a[SIZE];.

C++ sizeof different result for the same value

I want to calculate the 'sizeof' array:
char* arr[] = { "abc", "def" };
When I call sizeof manually, immediately after the initialization of the array, it works fine. However if I pass the array to some function, It doesn't give the same result.
int test(char* b[]) {
return (int)sizeof(b);
}
int _tmain(int argc, _TCHAR* argv[])
{
char* arr[] = { "abc", "def" };
int p = test(arr); // gives 4
int k = sizeof(arr); // gives 8
...
}
So what's the problem? Sorry for the newbie question, but I really miss it.
When you use sizeof on arr in _tmain, you're taking the size of the array itself, which is 2 * sizeof(char*) = 2 * 4 = 8 on your architecture, because your char*s occupy 32 bits = 4 bytes.
When you use sizeof on b in test, you're taking the size of a pointer to the first element of the array, which is sizeof(char**) = 4 on your architecture. The reason you're taking the size of the pointer and not the array is that you can't pass arrays as such to functions - instead, you pass them via a pointer to their first element. The information about the actual size of the array is thus lost in the call. Put another way, the signature of your function test is equivalent to int test(char **b).
This is because when you call a function in C or C++, arrays decay to pointers.
In the first case, the compiler sees arr as an array; in the second case, all it sees is a pointer to a pointer.
At point where test is defined, compiler cannot see what b points to. So, sizeof gives the size of a pointer (actually, size of a pointer to pointers).
Inside main, it can see perfectly well that real size is two pointers.
There really is no such thing as passing array into function - only pointer to array is passed. The [] form is just syntactic sugar.
You lose the size information when calling test because you array decays to a pointer.
You have to pass the size of the array as additional parameter, or fix it in the parameter type.
Welcome to C++.
You cannot pass an array to a function at all. In C++, arrays decay to pointers most of the time. You are trying to pass an array but in fact passing a pointer, and your second sizeof evaluates to the size of that pointer.
You should not care about any of this. Arrays are specialized low-level data structures that should be only used to implement higher-level abstractions. Use std::vector instead.

Cannot convert from 'int *' to 'int []'?

I know this might be a common question but I have tried to search but still cannot find a clear answer.
I have the following code:
int* f() {
int a[] = {1,2,3};
return a;
}
int main() {
int a[] = f(); // Error here
getch();
return 0;
}
This code produces the error message: "Cannot convert from 'int *' to 'int []'"
I found this quite strange because I have read that pointer and array are similar. For example, we can use a[i] instead of *(a + i).
Can anyone give me a clear explanation, please?
There are actually two errors in this code.
Firstly, you are returning the address of a temporary (the int array within f), so its contents are undefined after the function returns. Any attempt to access the memory pointed to by the returned pointer will cause undefined behaviour.
Secondly, there is no implicit conversion from pointers to array types in C++. They are similar, but not identical. Arrays can decay to pointers, but it doesn't work the other way round as information is lost on the way - a pointer just represents a memory address, while an array represents the address of a continuous region, typically with a particular size. Also you can't assign to arrays.
For example, we can use a[i] instead of *(a + i)
This, however, has little to do with the differences between arrays and pointers, it's just a syntactic rule for pointer types. As arrays decay to pointers, it works for arrays as well.
The type int[] doesn't actually exist.
When you define and initialize an array like
int a[] = {1,2,3};
the compiler counts the elements in the initializer and creates an array of the right size; in that case, it magically becomes:
int a[3] = {1,2,3};
int[] used as a parameter to a function, instead, it's just plain int *, i.e. a pointer to the first element of the array. No other information is carried with it, in particular nothing about the size is preserved. The same holds when you return a pointer
Notice that an array is not a pointer: a pointer can be changed to point to other stuff, while an array refers always to the same memory; a pointer does not know anything about how big is the space of memory it points to, while the size of an array is always known at compile time. The confusion arises from the fact that an array decays to a pointer to its first element in many circumstances, and passing it to a function/returning it from a function are some of these circumstances.
So, why doesn't your code work? There are two big errors:
You are trying to initialize an array with a pointer. We said that an int * doesn't carry any information about the size of the array. It's just a pointer to the first element. So the compiler cannot know how big a should be made to accomodate the stuff returned by f().
In f you are returning a pointer to a variable that is local to that function. This is wrong, because a pointer does not actually store the data, it only points to where the data is stored, i.e. in your case to the a local to f. Because that array is local to the function, it ceases to exist when the function exits (i.e. at the return).
This means that the pointer you are returning points to stuff that does not exist anymore; consider the code:
int * a = f();
This initialization works, and you can try to use a later in the function, but a will be pointing to the no-longer existent array of f; in the best case your program will crash (and you'll notice immediately that you've done something wrong), in the worst it will seem to work for some time, and then start giving strange results.
int * and int [] are similar but different.
int * is a real pointer, meanwhile int[] is an array reference ( a sort of "constant pointer" to the begin of the data) wich cannot be modified. So, a int * can be threated like a int [] but not viceversa.
You can use a[b] and*(a+b) interchangeably because that is exactly how a[b] is defined when one of a or b is a pointer and the other is of integer or enumeration type.
Note: This also means that expressions like 42[a] are perfectly legal. Human readers might object strongly, but the compiler won't bat an eye at this.