Why is the j at the end of the execution an "1"?
Compiled with following flags gcc -m32 xxx.c on a 64 bit Unix machine.
#include <stdio.h>
int main(int argc, char **argv)
{
int *q = (int *)2;
char *r = (char *)1;
int j;
q++;
r++;
j = (int *)q - (int *)r;
printf("j = %d\n", j);
return 0;
}
Code is only for academic purposes! ;)
First of all, in theory this is all undefined behavior, since you are using pointers to not allocated memory, comparing stuff that do not belong to the same array etc.
Now, putting this aside, once you have clear the mechanics of pointer arithmetic it's quite easy:
int *q = (int *)2;
char *r = (char *)1;
int j;
// a pointer is incremented in steps of the size of its "base type"; this
// allows to move to the next element if you are pointing inside an array
q++; // q=(int*)(2+sizeof(int))=(int *)6
r++; // r=(char *(1+sizeof(char))=(int *)2;
// again, the difference between two pointers is computed in units of the
// base type; in an array, this gives you how many places are two elements
// apart
j = (int *)q - (int *)r; // (6-2)/sizeof(int)=1
(here sizeof(int) is 4 since you are compiling with gcc and -m32, and sizeof(char) is 1 by definition of sizeof)
Note: You are invoking undefined behavior, there's nothing saying that the alignment of int is 2 or less; nor are q and r members of the same array, or the same object.. you should never do what you are doing in your snippet.
Ignoring the obvious undefined behavior
One should never take undefined behavior lightly, the result of your code is highly implementation specific, and can do pretty much anything. But theoretically the code will be interpreted as described below, but there is no such guarantee.
j will be the distance between q and r (both interpreted as int*).
Incrementing a pointer to int will move it sizeof(int) bytes forward, while incrementing a pointer to char will move it sizeof(char) byte forward.
Subtracting one pointer from another yields the number of elements between them, not the number of bytes.
A few assumptions, and a detailed description
Assuming that the underlying implementation has sizeof(int) = 4, we will have the following pseudo-code:
int_ptr q = 2
char_ptr r = 1
/* ++q -> */ value_of(q) += 4; // sizeof(int) = 4, value_of(q) = 6
/* ++r -> */ value_of(r) += 1; // sizeof(char) = 1, value_of(r) = 2
int j = int_ptr(q) - int_ptr(r); // j = 1
// (value_of(q) - value_of(r))/sizeof(int)
The answer: j = 1
Related
According to the C standard (SO link 1 and link 2) we cannot access an element of a row using out-of-bounds index:
int x[10][10] = ...; // initialize x
int q = x[0][10]; // This is an out-of-bounds access
Then is it valid to initialize the array using the following loop?
int *p = &x[0][0];
for (int i = 0; i < 100; ++i)
p[i] = 0;
If this is not valid, then is it valid to initialize x using memset(&x[0][0], 0, sizeof(x))?
int *p = &x[0][0];
memset(p, 0, sizeof(x))?
edit:
I wonder whether the answers are different in C++ as well..! :)
The loop is not valid, see the comments by #EricPostpischil .
Yes, the memset approach is valid too. But it is not preferred solution. It operates on individual bytes so it can only ever be reasonably used for zeroing the memory.
C++
Value initialization T array[10][10] = {}; zeroes the array of primitives types, calls default constructors for classes.
std::fill(p,p+100,value) for assigning a specific value.
There is not standard way how to initialize an array to non-zero values without listing them.
std::array<T,N> is the preferred way for arrays of known size.
C
cppreference
There is no special construct in C corresponding to value initialization in C++; however, = {0} (or (T){0} in compound literals) (since C99) can be used instead, as the C standard does not allow empty structs, empty unions, or arrays of zero length.
So, in case of nested arrays, use T array[10][10] = {{0}};.
You asked in title:
Can I use memset to initialize a 2 dimensional array?
Yes, as memset(...) only cares about byte count, you could use it like:
int x[10][10];
memset(&x, 0, sizeof(x));
But in C++, an empty initializer-list would do same, like:
int x[10][10] = {};
And in C since C99 (as mentioned in comments), we clould do instead:
int x[10][10] = {{0}};
Anyway, you say:
int q = x[0][10]; // This is an out-of-bounds access
Then asked is following valid:
int *p = &x[0][0];
for (int i = 0; i < 100; ++i)
p[i] = 0;
Well yes, but only because you do something as simple as setting to zero, a more complex logic could require you to loop 2 dimensionally, like:
for (int x = 0; x < 10; ++x) {
for (int y = 0; y < 10; ++y) {
myArray[x][y] = something_more_complex_here;
}
}
I have some code like this :
int n;
cin >> n;
int array[n];
for (int i = 0; i < n; ++i) {
cin >> array[i];
}
int tmp[n - 1];
tmp[0] = 1;
With input : 1 10 I found that the value of array[0] was changed , instead of 10 it has the same with tmp[0].
Then I realized with that input the length of tmp[] became zero. So I print the address of array[] and tmp[] with:
printf("%d\n %d\n", array, tmp);
and found they had the same address.
I want to figure out what will happen if an array has a length of 0; so I tried this:
int array[1];
array[0] = 10;
int tmp[0];
tmp[0] = 1;
address:
array[]: 1363909056
tmp[] : 1363909052
It looks just like the previous code (except the input part). But tmp[0] and array[0] has different values and address now.
And I'm really confused that tmp has smaller address then array.
So my question is:
What will happen if I declare an array of length zero?
Why these two codes works different? (they look the same to me :) )
This is called "undefined behavior". After declaring, in your case
int tmp[0];
The next thing that happens is:
tmp[0]=1;
Since tmp[0] does not exist, this is undefined behavior. Your problem is not that the array was declared with size 0 (that's not exactly kosher on its own merits, but is not the issue here), but the undefined behavior as a result of overwriting memory past the end of the array.
I'm in a data structures course, our midterm is coming up and our practice midterm asks if each line is valid syntax:
int num = 10;
int *p, *q;
p = #
q = p; //valid
*p = q; //invalid, int* cannot be assigned to int
(*p)++; //valid
&num+1; //valid ********
p++; //valid ********
So the last two lines of code, as I understand it, add 1 to the address of the num variable.
What purpose would this have in coding?
In this case, that would lead to undefined behavior. It would address the int that follows num in memory, but there is no defined way to tell what that would be. Nonetheless, it is valid syntax.
It would make a great deal more sense if your pointer pointed to an element of an array instead of a scalar. In that case, addressing the next int is reasonable. But in both cases the syntax is valid.
A purpose this would have in coding is to write tests such as:
void f ( size_t length, int data[length] )
{
assert( 0 == length % 4 );
for ( int* p = data; p < data + length; p += 4 )
do_stuff_with_subarray( p, 4 );
return;
}
The loop condition p < data + length bounds-checks the pointer by comparing it to the address one past the end of the array. Dereferencing this address would be undefined behavior, but comparing to it is not. (In this simplistic example, though, there will be UB if do_stuff_with_subarray() ever reads past the end of an array whose length is not divisible by 4.)
I must implement a bunch of methods that allocates, modify and free a 2D array of c-style string. I cannot use string nor vectors nor any stl container.
getNewMat :
char*** getNewMat(int w, int h){
char*** newMat = new char**[h];
for(int i = 0 ; i < h ; i++){
newMat[i] = new char*[w];
for(int j = 0 ; j < w ; j++)
newMat[i][j] = NULL;
}
return newMat;
}
fillMat
void fillMat(char***mat, int x, int y, char* newEl){
mat[y][x] = newEl; //this will produce a segfault (even with good index)
}
showMat :
void showMat(char*** mat, int w, int h){
for(int i = 0 ; i < h ; i++){
for(int j = 0 ; j < w ; j++)
cout << mat[i][j];
}
cout << endl;
}
so, can anyone please tell me what's wrong with this?
In your fillMat method you do this:
mat[y][x] = newEl;
Where x and y are the dimensions of the two ranks of the array. That line will cause a segmentation fault because you're going outside the bounds of the array. mat is indexed from 0 to length - 1 and setting by x and y is going 1 outside the bounds of the array.
Maybe you meant to loop through and set them:
for (int i = 0; i < y; ++i)
{
for (int k = 0; k < x; ++k)
mat[i][k] = newEl;
}
Moreover, inside your showMat function you have this:
cout << showMat[i][j];
I think you meant for that to be mat:
cout << mat[i][j];
newMat[i][j] = NULL - it's a bad idea. In showMat you will try to dereference a NULL pointer - this is UB and may cause a segfault.
char* - it's not a string - it's just a pointer to char, that may points to memory location, where can be beginning of string. If you want to work with it like with a string, you should allocate memory for it too.
mat[y][x] = newEl - it's a bad idea too. As I already said, char* is not a string, so, you can't just use assignment operator to copy data from one C-string into another. You should use std::copy or std::strncpy.
Do not forget to free allocated memory after using.
You should implement your own string class - it's the better solution, I can see there. At least, because it simpler and easier to understand.
I must implement a bunch of methods that allocates, modify and free a
2D array of c-style string. ...snip... so, can anyone please tell me
what's wrong with this?
A "c-style string" isn't a type. It's a representation of data within a type. '\0'-terminated strings are typically stored within char arrays, but you could store one just as easily in a unsigned int array. For example:
unsigned int message[32] = { 0 };
strcpy((char *) message, "Hello, world!");
printf("%s\n", (char *) message);
I discourage programming like this, however micro-optimistic the benefits may seem. It's also possible to store a string in something that isn't an array. Consider that a char might be suitable for storing an empty string:
char x = '\0';
printf("%s\n", &x);
It's reasonable to assume that you meant "an array of array of array of char", when you said "2D array of c-style string". Let us carry on in that direction.
I don't know a lot about C++, but there's a list of property of arrays which you probably haven't thought about in your quest to mimic actual arrays. I'll summarise these using assertions:
#define x 7
#define y 13
#define z 1
char foo[x][y][z] = { 0 };
assert((char *) foo == foo[0]);
assert(sizeof foo == (char *) &foo[1] - (char *) &foo[0]);
assert(sizeof foo == x * y * z);
I'm not sure if you'll be able to solve your problem with any of these assertions passing in C++, but I'm open for any input from others as to hints as to how one might...
Arrays are contiguous. This means that newMat[x] + w and newMat[x+1], for values of x in 0 .. h-1. In your code, this isn't a reality, because you allocate newMat[x] and newMat[x+1] separately. Similarly, it is expected that newMay[0][y] == newMat[0][y+1] + n, where n is the maximum length of your strings. This can be a problem when using generic array sorting algorithms, because they might rely upon your arrays being contiguous.
The closest you might come to solving this problem seems to involve allocating only once per dimension, rather than h times for the first dimension and w for the second. This would look something like this:
char ***getNewMat(size_t w, size_t h, size_t n){
char ***newMat = new char **[h];
newMat[0] = new char *[h*w];
newMat[0][0] = new char[h*w*n];
for(size_t i = 0; i < h; i++){
newMat[i] = newMat[0] + i * w;
for (size_t j = 0; j < w; j++) {
newMat[i][j] = newMat[0][0] + i * w * n + j * n;
}
}
return newMat;
}
One side-effect of arrays being contiguous is that you can't assign C-style strings by merely changing the pointer within the array to point to a different location. The pointer is the result of a conversion from an array expression to a pointer expression which isn't an lvalue. As I said earlier, I don't know much about C++, but in C that means the following code can't compile:
char foo[x][y][z] = { 0 };
foo[a][b] = "hello";
However, the following code can compile:
char *foo[x][y] = { 0 };
foo[a][b] = "hello";
The former might constitute an array of C-style strings, but the latter can't because of the contiguity rule we've covered, and the fact that it starts off with most if it's elements pointing to NULL, a pointer which can't point to anything let alone strings. There might be some operator overloading magic you can perform to permit the former to compile. I'm also open for any hints in the right direction to provide an example for the OP, here.
There is a pointer-to-an-Array of Arrays i.e. NameList in the code. I want the contents of each of the Arrays in the Pointer(NameList) to get printed one by one. The below code is not able do the task. Pls. help.
int Data1[] = {10,10};
int Data2[] = {20,20};
int Data3[] = {30,30};
int *NameList[] = {Data1, Data2, Data3};
main()
{ Function(NameList); }
Function(int *ArrayPointer)
{
int i, j, index=0;
for (i=0; i < 3; i++)
{
for (j=0; j < 2; j++)
{
//It does not print the data
printf("\nName: %s", ArrayPointer[index++]);
}
index=0; //Counter reset to 0
ArrayPointer++; //Pointer is incremented by one to pick next array in the pointer
}
}
print("code sample");
Another note from the original poster of the question:
I have completed a pacman game in Turbo C. I was polishing some graphics routines so that it can be reused again easily. This is only a small sample created for the purpose of help and understanding the concept. All data in the code actually are char arrays for sprites. Now i simply want to call a function passing the pointer so that each arrays in the pointer are drawn to the screen. How can this code be modified to handle this? Im actually stuck up here.
Darn it litb, once again you beat me to the punch by mere minutes. (If only I didn't have kids who keep waking up...)
Ahh, what the hell. Perhaps this will still be useful to somebody.
Oh, and just to nail this thing down:
Arrays, such as int a[4] allocate memory space for their data.
Pointers, such as int * p allocate just enouch memory space for a pointer to another spot in memory.
That's why we can use sizeof on arrays and get the full memory footprint, but not on pointers.
Other than that little distinction, there really isn't a big difference between int[] and int*. (Consider how many folks declare *main(int argc, char **argv) vs main(int argc, char * argv[]).)
ATTENTION: All memory addresses here are fictional. I'm just making them up to illustrate a point.
Given:
int Data1[] = {10,11};
int Data2[] = {20,22};
int Data3[] = {30,33};
We now have 3 blocks of memory. Say:
0xffff0000-0xffff0003 with a value of (int)(10)
0xffff0004-0xffff0007 with a value of (int)(11)
0xffff0008-0xffff000b with a value of (int)(20)
0xffff000c-0xffff000f with a value of (int)(22)
0xffff0010-0xffff0013 with a value of (int)(30)
0xffff0014-0xffff0017 with a value of (int)(33)
Where:
Data1 == & Data1 [0] == 0xffff0000
Data2 == & Data2 [0] == 0xffff0008
Data3 == & Data3 [0] == 0xffff0010
NO, I'm not going to get into big-endian vs little-endian byte ordering here!
Yes, in this case, Data1[2] == Data2[0]. But you can't rely on your compiler laying things out in memory the same way I've laid them out here.
Next:
int *NameList[] = {Data1, Data2, Data3};
So we now have another block of memory. Say:
0xffff0018-0xffff001b with a value of (int*)(0xffff0000)
0xffff001c-0xffff001f with a value of (int*)(0xffff0008)
0xffff0020-0xffff0023 with a value of (int*)(0xffff0010)
Where:
NameList == & NameList [0] == 0xffff0018
Note that NameList is of int ** type, and NOT int* type!
We can then write:
void Function(int **ArrayPointer)
{
for ( int i=0; i < 3; i++ )
for ( int j=0; j < 2; j++)
printf("Name: %d\n", ArrayPointer[i][j] );
}
int main() { Function(NameList); }
ArrayPointer resolves to (int**)0xffff0018.
ArrayPointer[0] == *( (int**) 0xffff0018 ) == (int*)(0xffff0000) == Data1.
ArrayPointer[0][1] == *( ( * (int**) 0xffff0018 ) + 1 ) == (int) * ( (int*)0xffff0000 + 1 ) == (int) * (int*) 0xffff0004 == Data1[1].
You may want to review pointer arithmetic: array[N] == *( array + N )
main has to return a type. You forget to put "int" as a return type (implicit int in C++ is banned).
Having said that, i'm not sure what you mean by
// It does not print the data
printf("\nName: %s", ArrayPointer[index++]);
ArrayPointer[index++] would, as it is defined in the parameter list, return an int. How is that supposed to store a name ? It will store an integer!
Once again, that said, you can't call that Function (pun intended) with that particular argument. Let's view your types:
int Data1[] = {10,10};
int Data2[] = {20,20};
int Data3[] = {30,30};
int *NameList[] = {Data1, Data2, Data3};
Data1 Data2 Data3 NameList
int[2] int[2] int[2] int*[3]
Contrary to what you said, NameList is not a pointer to an array of arrays. I feel i need to show you what that would be:
int (*NameList)[N][M] = Some3DimensionalArray;
That wouldn't make sense at all. So what do you have?
Data1 = array of 2 int
Data2 = array of 2 int
Data3 = array of 2 int
NameList = array of poiners to int
That is what you got. And you pass NameList to a Function that wants a pointer to an int. It must fail already at the time you call Function in main! I've got no idea what you mean by name in that line in Function. But if you want to print out the integers that are stored in the arrays pointed to (by pointers to their first element), you can do it like this (keeping your code as much as i can):
// don't forget the return type, mate. Also see below
void Function(int **ArrayPointer)
{
int i, j, index=0;
for (i=0; i < 3; i++)
{
for (j=0; j < 2; j++)
{
// It does not print the data. It is not a string,
// but an int!
printf("\nName: %d\n", ArrayPointer[i][index++]);
}
index=0; //Counter reset to 0
// no need to increment the pointer. that's what the indexing by i
// above does
// ArrayPointer++;
}
}
I keep preaching people asking questions the difference between a pointer and an array. It's crucial to write correct code. I hope i could help. At the end, just a little though about the difference between int[] and int*. The first is an incomplete array type, while the second is a complete type (pointer to int):
typedef int Single[]; // array of indeterminate size.
typedef int *Pointer; // pointer to int
Single s1 = { 1, 2, 3, 4 }; // works!
Pointer s2 = { 1, 2, 3, 4 }; // no no, doesn't work. s2 wants an address
s2's type now has a type different from int[], because you initialized the array which would have incomplete type, the array s1 become complete after defined. It has type of int[4]. In parameter lists, however, there exist a special rule, which will cause any array type (even complete ones!) to be equivalent to a pointer to their first argument. Thus:
void f(int *a) <=> void f(int a[]) <=> void f(int a[42]);
void f(int (*a)[42]) <=> void f(int a[][42]) <=> void f(int a[13][42])
// ...
That's because you can't pass arrays by value. The compiler abuses that to make array types equivalent to pointers to their first element. Same deal with functions:
void f(int a()) <=> void f(int (*a)())
Because you can't pass functions by value (huh, doesn't even make sense at all to me), the compiler abuses it to make a function type in a parameter list equivalent to a pointer to that function type.
int Data1[]
has the type of
int *
and
int *NameList[]
has the type of
int **
You have a two-dimensional array there. Most likely you meant:
Function(int **ArrayPointer)
On that note, ANSI C/C89/C99 functions have an explicit return type (or void), e.g.
int main() { ... }
void Function() { ... }
The value pointed to by ArrayPointer is an int, not a string. Thus
printf("\nName: %s", ArrayPointer[index++]);
Should be written as something else.
A third thing: index == j in your code. Thus index can be removed in favor of j.
i and j are probably not good variable names here because ArrayPointer is not name describing a list of something.
If you need more help, please post what you're looking to do, because you code has several bugs (and oddities) in it.
Judging by your "answer" (you really should have edited your original post and added this information), you probably want something like this:
void draw_all_sprites(Sprite *sprites, size_t num_sprites)
{
Sprite *cur_sprite;
size_t i;
for(i = 0; i < num_sprites; ++i)
{
draw_sprite(cur_sprite);
++cur_sprite;
}
}
A fairly simple for loop to iterate through elements in an array.
Paramod,
is there a function you need to call that takes something along the lines of
void drawSprite(int *data, int rows, int cols)
?
Then you need to have all data in a single chunk of memory. In your example, the compiler allocates a separate chunk for every row, and then another chunk to hold the three pointers to rows. Thus, the array is kept in 4 different places.
What you need is a multidimensional array rather than array of arrays. Initialize your data like this:
int data[3,2] = {{10,10},{20,20},{30,30}};
Then you can call your function like this:
drawSprite(&data[0,0], 3, 2);
Using multidimensional array places all elements in one block of memory. The advantage is, you can pass the piointer to first element, and you know where all other elements are. The disadvantage - all rows are allocated the same size.
I made some corrections in your program please find them and compare. I know its too late for the response. But I saw this today itself.
int Data1[] = {10,10};
int Data2[] = {20,20};
int Data3[] = {30,30};
int *NameList[] = {Data1, Data2, Data3};
main()
{
Function(NameList);
}
Function(int *ArrayPointer)
{
int i, j, index=0;
for (i=0; i < 3; i++)
{
for (j=0; j < 5; j++)
{
//It does not print the data
printf("\nName: %d\n", *((int *)ArrayPointer[i] + index));
index++;
}
index=0; //Counter reset to 0
}
}
Explanation:
When you pass NameList to Function as a pointer to an integer, what gets passed is the address of the first element of the array, which happens to be Data1 (an address to an array). But since this address is held in an array of ints, it will be considered as an integer. To make it behave like an address to an array(or, for that matter pointer to an int) you need to cast it to (int *). Thats what I did in :
printf("\nName: %d\n", *((int *)ArrayPointer[i] + index));