Reputation: 71
What is the problem with the following code now?
int main(){
union {
char arr[10];
int var;
} u;
int *ptr_var= (int*) &(u.arr[1]);
*ptr_var = 42;
}
Upvotes: 0
Views: 149
Reputation: 1
This is architecture dependent. I would guess the standard may again say the behavior is "undefined". I am getting different results when running it on different platforms:
1> Linux on X86: runs fine without a problem 2> Solaris on sparc: "Bus error (core dumped)".
Upvotes: 0
Reputation: 11785
This is compiling nice and easy here. No segmentation fault. What is exactly the output of your compiler?
Here you can see:
#include <stdio.h>
int main()
{
int *ptr_var;
union
{
char arr[10];
int var;
} u;
u.arr[0]='A';
u.arr[9]='\0';
ptr_var = (int*) &u.arr[1];
*ptr_var = 0x2a;
printf("%s\n", u.arr);
printf("%d(d)=%x(x)\n",u.var, u.var);
}
And the answer is:
cpp/test/temp$ gcc union.c -o union
cpp/test/temp$ ./union
A*
10817(d)=2a41(x)
cpp/test/temp$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
It is a fine way to move bits around. Maybe your segfault is in another area of the program. See this test:
*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);
ptr_var = (int*) &u.arr[1];
*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);
ptr_var = (int*) &u.arr[2];
*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);
And you get:
16(d)=10(x)
4112(d)=1010(x)
1052688(d)=101010(x)
Take care, Beco.
Upvotes: 1
Reputation: 26144
Note: a correct answer has already been given, this is simply another way to explain the background.
When accessing objects in memory, most machines require that the objects are aligned. This mean that a four-byte (32 bit) object must be placed on an address that is dividable by four. This originates in the fact that the CPU is connected with the memory using a data-bus, in our example the bus is 32 bits. If the CPU would be to support unaligned accesses, it would have to request two accesses to the memory and puzzle them together. Instead, most architectures consider this an illegal operation.
In your case, you start with a union, which is stored at an even four-byte address. Then you step one byte forward and try to access an int
at an address that is must definitely not an even multiple of the size.
Upvotes: 4
Reputation: 92884
Are you sure this is giving segfault? The title is misleading!!
AFAIK on older architecture this would result in bus error. But as this post explains you don't get to see bus error these days.
This would cause bus-error because the array/int union ensures that character array arr
is also at a reasonably aligned address for an integer that &arr[1]
is definitely not aligned properly for the integer. And then you try to store sizeof(int)
bytes into an address that is aligned only for single-byte access. Arghh!!!
Upvotes: 3