Annoyances with pointer offsets.

Started by
16 comments, last by iMalc 18 years, 9 months ago
As part of my DIB implementation, I'm reminded of this little annoyance.

int luiMain[2];

luiMain[0] = 10;
luiMain[1] = 10;

*(&luiMain[0] + 1) == luiMain[1]

In order to add 1 byte, instead of 4 bytes, you gotta cast it...
#include <stdio.h>
void main()
{
	int *laiMain;
	int luiX;
	laiMain = malloc(4*5);
	laiMain[0] = 1;
	laiMain[1] = 5;
	laiMain[2] = 10;
	laiMain[3] = 15;
	laiMain[4] = 20;
	
	for(luiX=0;luiX<=8;luiX++) printf("laiMain[%d]=%d\n", luiX, *(((char *)&laiMain[0]) + luiX));
}

Anyone know a way to disable this? lol, why did they decide on this?! It really doesn't help at all! [Edited by - Thevenin on July 4, 2005 8:41:48 PM]
Advertisement
Looks like you're trying to inspect individual bytes within each int.

Do you use/understand hex? If so... why not use this instead?

	int luiX;	laiMain[] = { 1, 5, 10, 15, 20 };        for(luiX = 0; luiX < sizeof(laiMain); luiX++)             printf("laiMain[%d]=%.8X\n", luiX, &laiMain[luiX]);


Seems like that would be the simplest way to inspect bytes (in groups of four)

I'm at a loss as to why you need to iterate through the array of ints one byte at a time, though [smile]
my_life:          nop          jmp my_life
[ Keep track of your TDD cycle using "The Death Star" ] [ Verge Video Editor Support Forums ] [ Principles of Verg-o-nomics ] [ "t00t-orials" ]
The need arose because I went and did this...

void *Surface = [int][int][struct loRGB][struct loRGB][struct loRGB]...

The first two ints are the width and height, and the rest (Roughly 250k) are all RGB structs.

Inaddition, instead of calling it a void, I went and called it...

struct tRGB *Surface = [int][int][struct loRGB][struct loRGB][struct loRGB]...

So now its impossible to access the first two ints properly without breaking off of the "Multiple of 3" rule imposed by the automated structure cast.

I work with Hex quite often when cheating on DungeonCrawl, but in the programming environment I've never figured out what 0x means, is that just a symbol representing that the following is in Hex?
They did it that way because if you have a pointer to something it makes no sense for p+1 to point into the middle of it. It also falls out naturally from the syntax for arrays.
-Mike
Quote:Original post by Anon Mike
They did it that way because if you have a pointer to something it makes no sense for p+1 to point into the middle of it. It also falls out naturally from the syntax for arrays.


But, but but but.. but

Array[x+1] == I'm ok with that +1 shifting it the sizeof(element).
Array[x] + 1 == This is ludakris, it should shift it 1 byte, not sizeof(element) [headshake]
Quote:Original post by Thevenin
Array[x+1] == I'm ok with that +1 shifting it the sizeof(element).
Array[x] + 1 == This is ludakris, it should shift it 1 byte, not sizeof(element) [headshake]


Those are quite diffrent, one references the element at element (x + 1) the other is the element at x and has one added to it. But let's pretend you ment
&Array[x] + 1
then that wouldn't reference an element but is equal to Array + x + 1, and I guess understanding that is the source of the your problem. Array[x] is just convinent shorthand for *(Array + x), actually it extends so far as to actually being able to write x[Array] (disregarding the fact that anyone who actually use that construct should be shot.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Quote:Original post by Thevenin
The need arose because I went and did this...

void *Surface = [int][int][struct loRGB][struct loRGB][struct loRGB]...

The first two ints are the width and height, and the rest (Roughly 250k) are all RGB structs.

Inaddition, instead of calling it a void, I went and called it...

struct tRGB *Surface = [int][int][struct loRGB][struct loRGB][struct loRGB]...

So now its impossible to access the first two ints properly without breaking off of the "Multiple of 3" rule imposed by the automated structure cast.

I work with Hex quite often when cheating on DungeonCrawl, but in the programming environment I've never figured out what 0x means, is that just a symbol representing that the following is in Hex?
Can you please show what you mean in terms of real C++ code with regards to tRGB above. You can't possibly mean a 5-dimensional array!

Also, please explain what you mean by a "multiple of 3 rule". Those first two ints are aligned to int boundaries as far as I'm concerned from what you've posted this far.

I do not see a reason for you to attempt to circumvent the automatic pointer offset arithmetic, thus far. If it's behaviour seems wrong, then you are probably doing something in a bad way. Show some real code so we can show you the way that you should really be doing it.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
KISS. (I assume plain C.)

typedef struct tRGB_s {  int x;  int y;  // The easiest thing is to just add a level of indirection.  // C's unbelievably weak typing also lets you get away with just declaring  // an array[1] here, and then over-allocating memory accordingly to create  // the struct.  struct loRGB* data;} tRGB;tRGB* createTRGB(int x, int y) {  tRGB* thing = malloc(sizeof tRGB); if (!thing) return NULL;  thing->x = x; thing->y = y; thing->data = malloc(sizeof (struct loRGB) * x * y);  if (!thing->data) { free(thing); return NULL; }  return thing;}int destroyTRGB(tRGB* target) {  if (!target) return -1;  free(target->data); // it is an invariant that this won't be NULL.  free(target);  return 0;}tRGB* cloneTRGB(tRGB* src) {  tRGB* result = createTRGB(src->x, src->y); if (!result) return NULL;  for (int i = 0; i < src->x * src->y; ++i) { result->data = src->data; }  return result;}int assignTRGB(tRGB* src, tRGB* dest) {  if (!(src && dest)) return -1;  tRGB* other = cloneTRGB(src); if (!other) return -1;  dest->x = other->x; dest->y = other->y;  free(dest->data); dest->data = other->data; free(other);  return 0;}


In C++ this kind of thing becomes much easier:

struct tRGB {  int x;  int y;  loRGB* data;  tRGB(int x, int y) : x(x), y(y), data(new loRGB[x*y]) {}  tRGB(const tRGB& other) x(other.x), y(other.y), data(new loRGB[x*y]) {    for (int i = 0; i < x*y; ++i) { data = other.data; }  }  tRGB& operator=(const tRGB& rhs) {    // copy and swap idiom, for exception safety. I used something similar in    // the C code.    tRGB other(rhs);    x = other.x; y = other.y; std::swap(data, other.data);  }  ~tRGB() { delete[] data; }};
I do not mean a 5-dimensional array.

(&array[1] + 1) is EXACTLY equivalent to (&array[2])

I'm fine with this if its bytes (Since +1 byte <=> the next byte), but when working with structures (Or any variable greater than 1 byte in size), I disagree with the standards.

Quote:Original post by iMalcIf it's behaviour seems wrong, then you are probably doing something in a bad way. Show some real code so we can show you the way that you should really be doing it.


Ok.

You have a very large block of linear memory...
[][][][][][][][][][][][][][][][][]

You store int's in the first two
[int][int][][][][][][][][][][][][]

Than you store struct RGB (A structure of 3 unsigned characters) in the remaining.
[int][int][sturct RGB][sturct RGB][sturct RGB][sturct RGB][sturct RGB]...

And you call this a surface.

Now when you call my sDrawSurface() function, you don't have to specify the width and height of the surface your drawing, because it already knows, because its already in the surface itself (My reason for doing it this way).

Its really just this simple.

The "Multiple of 3" rule is reference to the fact, that I cannot say arrSurface[{Some Decimal Value Here}] and get the height.

Observe...
struct RGB MyRGBArray;

MyRGBArray[0] == 0th byte.
MyRGBArray[1] == 3rd byte.
MyRGBArray[2] == 6th byte.
MyRGBArray[3] == 9th byte.
MyRGBArray[4] == 12th byte.

However, my the width and height are on the 0th byte && 4th byte.

And so I was hoping....

&MyRGBArray[0] + 4 == 4th byte.

However, it actually equals....

&MyRGBArray[0] + 4 == 12th byte.

Which is ludakris!

arrays are meant to store 1 data type. array indexing and pointer arithmetic work the same way. use a byte as your pointer type if you want to increment by the size of a byte.

How about instead of trying to hack something into working, you use the right tool for the job, such as a struct?

struct RGB
{
unsigned char r,g,b;
}

struct mysurfacestruct
{
int a;
int b;
RGB color1;
RGB color2;
RGB color3;
}

then you can have an array of these structs if you want.

This topic is closed to new replies.

Advertisement