473,378 Members | 1,523 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Can I do ANYTHING on allocated memory?

Does any of the following constitute undefined behavior? Once I allocate memory,
can I do with it whatever I want (as in the example, use memory allocated as
char *, as memory where I store integers)?

#include <stdio.h>
#include <stdlib.h>

int main(void) {
char *a;
int *x, *y;
a = (char *) malloc(2 * sizeof(int));
// here's the part I'm wondering about
x = (int *) a;
y = (int *) a + sizeof(int);
*x = 10;
*y = 20;
printf ("%d %d\n", *x, *y);
return 0;
}

--
"It is easy in the world to live after the world's opinion; it easy in solitude
to live after our own; but the great man is he who in the midst of the crowd
keeps with perfect sweetness the independence of solitude."
Ralph Waldo Emerson, Self-reliance 1841
http://pinpoint.wordpress.com/

Jan 11 '07 #1
17 1309

"Sourcerer" <en****@MAKNIgmail.comwrote in message
Does any of the following constitute undefined behavior? Once I allocate
memory, can I do with it whatever I want (as in the example, use memory
allocated as char *, as memory where I store integers)?

#include <stdio.h>
#include <stdlib.h>

int main(void) {
char *a;
int *x, *y;
a = (char *) malloc(2 * sizeof(int));
// here's the part I'm wondering about
x = (int *) a;
y = (int *) a + sizeof(int);
*x = 10;
*y = 20;
printf ("%d %d\n", *x, *y);
return 0;
}
You are playing fast and loose with the C type system.
It is there to help you avoid alignment problems and other nasties, however
for backwards compatibility and certain low-level operations, C also gives
you the freedom to mess about with it.
Technically I think you are OK because pointers to char can be converted to
any other type. This is a hangover from the days when there were no void
pointers, so char *s were used instead.
However had you cast to a short *, and back, it would have been
implentation-defined behaviour. On the vast majority of machines int * and
short *s are the same and the cast is a no op. However it is just possible
that the short * throws some bits away which an int * needs, so a conforming
implementation could do anything it wants in response.
Jan 11 '07 #2
In article <eo**********@ss408.t-com.hr>,
Sourcerer <en****@MAKNIgmail.comwrote:
>Once I allocate memory,
can I do with it whatever I want (as in the example, use memory allocated as
char *, as memory where I store integers)?
You didn't allocate it as char *:
a = (char *) malloc(2 * sizeof(int));
You just allocated some memory, and (unnecessarily) cast it to char *
before assigning it to a. The memory returned by malloc() doesn't
have a type.

You can store whatever you like in it, provided that it fits and you
respect the alignment rules.
x = (int *) a;
Fine.

But you have a mistake here:
y = (int *) a + sizeof(int);
You have converted a to an integer pointer, then added sizeof(int) to
it. If sizeof(int) is 4, you have just added four int sizes to it,
i.e. 16 bytes. Adding to a pointer adds in units of the size of the
pointed-to object, so you want

y = (int *) (a + sizeof(int));
or
y = (int *) a + 1;

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jan 11 '07 #3
In article <lK*********************@bt.com>,
Malcolm McLean <re*******@btinternet.comwrote:
>You are playing fast and loose with the C type system.
No, apart from his mistake with the addition, he is using pointers
correctly.
>Technically I think you are OK because pointers to char can be converted to
any other type. This is a hangover from the days when there were no void
pointers, so char *s were used instead.
void * has replaced char * as the generic pointer type, but you can't
do arithmetic on void * pointers. char * (or unsigned char *) is the
type used to access memory as bytes, which are the units of C storage.

C guarantees that void * and char * have the same representation, but
the OP is not relying on that.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jan 11 '07 #4
"Sourcerer" <en****@MAKNIgmail.comwrites:
Does any of the following constitute undefined behavior? Once I
allocate memory, can I do with it whatever I want (as in the example,
use memory allocated as char *, as memory where I store integers)?

#include <stdio.h>
#include <stdlib.h>

int main(void) {
char *a;
int *x, *y;
a = (char *) malloc(2 * sizeof(int));
// here's the part I'm wondering about
x = (int *) a;
y = (int *) a + sizeof(int);
*x = 10;
*y = 20;
printf ("%d %d\n", *x, *y);
return 0;
}
Apart from the addition of sizeof(int), which actually adds
sizeof(int)*sizeof(int) bytes to the pointer, your code looks ok as
far as I can tell. But it could be simplified considerably (and made
more robust):

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int *x, *y;
x = malloc(2 * sizeof *x);
if (x == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
y = x + 1;
*x = 10;
*y = 20;
printf ("%d %d\n", *x, *y);
return 0;
}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 11 '07 #5
"Richard Tobin" <ri*****@cogsci.ed.ac.ukwrote in message
news:eo***********@pc-news.cogsci.ed.ac.uk...
In article <eo**********@ss408.t-com.hr>,
Sourcerer <en****@MAKNIgmail.comwrote:
>>Once I allocate memory,
can I do with it whatever I want (as in the example, use memory allocated as
char *, as memory where I store integers)?

You didn't allocate it as char *:
>a = (char *) malloc(2 * sizeof(int));

You just allocated some memory, and (unnecessarily) cast it to char *
before assigning it to a. The memory returned by malloc() doesn't
have a type.
Why is the cast unnecessary? malloc() returns void *
You can store whatever you like in it, provided that it fits and you
respect the alignment rules.
>x = (int *) a;

Fine.

But you have a mistake here:
>y = (int *) a + sizeof(int);
Sorry, this should've been y = (int *) (a + sizeof(int));

--
"It is easy in the world to live after the world's opinion; it easy in solitude
to live after our own; but the great man is he who in the midst of the crowd
keeps with perfect sweetness the independence of solitude."
Ralph Waldo Emerson, Self-reliance 1841
http://pinpoint.wordpress.com/

Jan 11 '07 #6
"Sourcerer" <en****@MAKNIgmail.comwrites:
"Richard Tobin" <ri*****@cogsci.ed.ac.ukwrote in message
news:eo***********@pc-news.cogsci.ed.ac.uk...
>In article <eo**********@ss408.t-com.hr>,
Sourcerer <en****@MAKNIgmail.comwrote:
>>>Once I allocate memory,
can I do with it whatever I want (as in the example, use memory allocated as
char *, as memory where I store integers)?

You didn't allocate it as char *:
>>a = (char *) malloc(2 * sizeof(int));

You just allocated some memory, and (unnecessarily) cast it to char *
before assigning it to a. The memory returned by malloc() doesn't
have a type.

Why is the cast unnecessary? malloc() returns void *
[...]

See question 7.7b in the comp.lang.c FAQ, <http://www.c-faq.com/>.
Questions 7.6, 7.7, and 7.7c are also relevant.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 12 '07 #7
Sourcerer wrote:
Does any of the following constitute undefined behavior? Once I allocate
memory, can I do with it whatever I want (as in the example, use memory
allocated as char *, as memory where I store integers)?
Please try to indent code so it is readable. Luckily, your example is
small enough this time, so we can proceed with cleaning that up.
#include <stdio.h>
#include <stdlib.h>

int main(void) {
char *a;
int *x, *y;
a = (char *) malloc(2 * sizeof(int));
^^^^^^^^
This C++-ism is unnecessary and bad practice in C.
// here's the part I'm wondering about
^^
C++-style comments introduced with '//' will not work with C89
compilers, and are a bad idea for code that you post, since your only
protection against line-wrap problems is keeping comments short, as you
have done.
x = (int *) a;
Because malloc returns space suitable aligned for any type, the above
will fly, but
y = (int *) a + sizeof(int);
Did you check to see where this actually pointed? (int *)a is an int
pointer; the next int will be at (int *)a + 1.
*x = 10;
*y = 20;
You may not own the place y currently points.
printf ("%d %d\n", *x, *y);
return 0;
}
Try this modified version of your code to see what the above comments
reflect:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char *a;
int *x, *y;
a = (char *) malloc(2 * sizeof(int));

x = (int *) a;

printf("The pointer-to-char a contains: %p\n"
"The pointer-to-int x = (int *)a contains: %p\n"
"The value of (int *)a + sizeof(int) is %p\n"
"The value of (int *)a + 1 is %p\n",
(void *) a, (void *) x, (void *) ((int *) a + sizeof(int)),
(void *) ((int *) a + 1));

y = (int *) a + sizeof(int);
*x = 10;
#if 0
/* I am not even going to try to assign to *y, as assigned above */
*y = 20;
/* or try to print its value */
printf("%d %d\n", *x, *y);
#endif
/* but this would be ok */
y = x + 1;
*y = 20;
printf("%d %d\n", *x, *y);

return 0;
}
[The results on one implementation]
The pointer-to-char a contains: 20d90
The pointer-to-int x = (int *)a contains: 20d90
The value of (int *)a + sizeof(int) is 20da0
The value of (int *)a + 1 is 20d94
10 20
Jan 12 '07 #8
Richard Tobin well.

Jan 12 '07 #9
On Thu, 11 Jan 2007 22:50:40 -0000, "Malcolm McLean"
<re*******@btinternet.comwrote in comp.lang.c:
>
"Sourcerer" <en****@MAKNIgmail.comwrote in message
Does any of the following constitute undefined behavior? Once I allocate
memory, can I do with it whatever I want (as in the example, use memory
allocated as char *, as memory where I store integers)?

#include <stdio.h>
#include <stdlib.h>

int main(void) {
char *a;
int *x, *y;
a = (char *) malloc(2 * sizeof(int));
// here's the part I'm wondering about
x = (int *) a;
y = (int *) a + sizeof(int);
*x = 10;
*y = 20;
printf ("%d %d\n", *x, *y);
return 0;
}
You are playing fast and loose with the C type system.
No, he is not, although he is risking undefined behavior if the
allocation fails and malloc() returns a null pointer, and as others
have pointed out his arithmetic for calculating the value to assign to
'y' is incorrect unless he happens to be on a platform where
sizeof(int) is 1.
It is there to help you avoid alignment problems and other nasties, however
for backwards compatibility and certain low-level operations, C also gives
you the freedom to mess about with it.
Technically I think you are OK because pointers to char can be converted to
any other type. This is a hangover from the days when there were no void
malloc() returns a pointer to void, and pointers to void and to char
are guaranteed to have the same size and representation. So assigning
the returned address to a pointer to char does not change it at all.
pointers, so char *s were used instead.
However had you cast to a short *, and back, it would have been
implentation-defined behaviour. On the vast majority of machines int * and
short *s are the same and the cast is a no op. However it is just possible
that the short * throws some bits away which an int * needs, so a conforming
implementation could do anything it wants in response.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jan 12 '07 #10
Sourcerer wrote:
"Richard Tobin" <ri*****@cogsci.ed.ac.ukwrote in message
news:eo***********@pc-news.cogsci.ed.ac.uk...
>In article <eo**********@ss408.t-com.hr>,
Sourcerer <en****@MAKNIgmail.comwrote:
>>>Once I allocate memory,
can I do with it whatever I want (as in the example, use memory allocated as
char *, as memory where I store integers)?

You didn't allocate it as char *:
>>a = (char *) malloc(2 * sizeof(int));

You just allocated some memory, and (unnecessarily) cast it to char *
before assigning it to a. The memory returned by malloc() doesn't
have a type.

Why is the cast unnecessary? malloc() returns void *
That is why the cast is unnecessary (in C, as opposed to C++).

--
Chris "electric hedgehog" Dollin
"We did not have time to find out everything we wanted to know."
- James Blish, /A Clash of Cymbals/

Jan 12 '07 #11
On Fri, 12 Jan 2007 00:20:32 +0100, "Sourcerer"
<en****@MAKNIgmail.comwrote:
>"Richard Tobin" <ri*****@cogsci.ed.ac.ukwrote in message
news:eo***********@pc-news.cogsci.ed.ac.uk...
>In article <eo**********@ss408.t-com.hr>,
Sourcerer <en****@MAKNIgmail.comwrote:
>>>Once I allocate memory,
can I do with it whatever I want (as in the example, use memory allocated as
char *, as memory where I store integers)?

You didn't allocate it as char *:
>>a = (char *) malloc(2 * sizeof(int));

You just allocated some memory, and (unnecessarily) cast it to char *
before assigning it to a. The memory returned by malloc() doesn't
have a type.

Why is the cast unnecessary? malloc() returns void *
Because in C there is defined an implicit conversion in either
direction between a pointer to void and any other pointer to object
type.
Remove del for email
Jan 13 '07 #12

"Richard Tobin" <ri*****@cogsci.ed.ac.ukwrote in message
C guarantees that void * and char * have the same representation, but
the OP is not relying on that.
Yes he is.
He is converting from void * to type x * to int *.
This only works if type x is a char *. Otherwise the type x * could throw
away information contained in the void * which is needed by the int *.
Very unlikely, but it is allowed.
Jan 13 '07 #13
In article <7o******************************@bt.com>,
Malcolm McLean <re*******@btinternet.comwrote:
>C guarantees that void * and char * have the same representation, but
the OP is not relying on that.
>Yes he is.
He is converting from void * to type x * to int *.
This only works if type x is a char *.
It does not rely on void * and char * haaving the same representation,
just that you can convert any pointer to and from char * safely.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jan 13 '07 #14
Richard Tobin wrote:
In article <7o******************************@bt.com>,
Malcolm McLean <re*******@btinternet.comwrote:
C guarantees that void * and char * have the same representation, but
the OP is not relying on that.
Yes he is.
He is converting from void * to type x * to int *.
This only works if type x is a char *.

It does not rely on void * and char * haaving the same representation,
just that you can convert any pointer to and from char * safely.
It doesn't even rely on that. You can safely convert any result from
malloc to and from any non-function pointer type. The only time pointer
casts can lose information (or worse) is if the pointer is not properly
aligned, but the pointer is the result from a call to malloc, so it
must be properly aligned.

Jan 13 '07 #15

"Harald van D?k" <tr*****@gmail.comwrote
Richard Tobin wrote:
>In article <7o******************************@bt.com>,
Malcolm McLean <re*******@btinternet.comwrote:
>C guarantees that void * and char * have the same representation, but
the OP is not relying on that.
>Yes he is.
He is converting from void * to type x * to int *.
This only works if type x is a char *.

It does not rely on void * and char * haaving the same representation,
just that you can convert any pointer to and from char * safely.

It doesn't even rely on that. You can safely convert any result from
malloc to and from any non-function pointer type. The only time pointer
casts can lose information (or worse) is if the pointer is not properly
aligned, but the pointer is the result from a call to malloc, so it
must be properly aligned.
You are confusing what will happen on any current implementation with what
is guaranteed by the standard.
Currently any exta bits in a pointer will represent an offset, so a cast
back can reconstruct them as zero. However it is not guaranteed that this is
the only purpose of extra bits.
Jan 13 '07 #16
Malcolm McLean wrote:
"Harald van D?k" <tr*****@gmail.comwrote
Richard Tobin wrote:
In article <7o******************************@bt.com>,
Malcolm McLean <re*******@btinternet.comwrote:

C guarantees that void * and char * have the same representation, but
the OP is not relying on that.

Yes he is.
He is converting from void * to type x * to int *.
This only works if type x is a char *.

It does not rely on void * and char * haaving the same representation,
just that you can convert any pointer to and from char * safely.
It doesn't even rely on that. You can safely convert any result from
malloc to and from any non-function pointer type. The only time pointer
casts can lose information (or worse) is if the pointer is not properly
aligned, but the pointer is the result from a call to malloc, so it
must be properly aligned.
You are confusing what will happen on any current implementation with what
is guaranteed by the standard.
The standard is a bit underspecified regarding pointer conversions, but
does clearly address this part in 6.3.2.3p7: "A pointer to an object or
incomplete type may be converted to a pointer to a different object or
incomplete type. If the resulting pointer is not correctly aligned57)
for the pointed-to type, the behavior is undeļ¬ned. Otherwise, when
converted back again, the result shall compare equal to the original
pointer."

Jan 13 '07 #17

"Harald van D?k" <tr*****@gmail.comwrote in message
Malcolm
It doesn't even rely on that. You can safely convert any result from
malloc to and from any non-function pointer type. The only time pointer
casts can lose information (or worse) is if the pointer is not properly
aligned, but the pointer is the result from a call to malloc, so it
must be properly aligned.
You are confusing what will happen on any current implementation with what
is guaranteed by the standard.
*The standard is a bit underspecified regarding pointer conversions, but
*does clearly address this part in 6.3.2.3p7: "A pointer to an object or
*incomplete type may be converted to a pointer to a different object or
*incomplete type. If the resulting pointer is not correctly aligned57)
*for the pointed-to type, the behavior is unde?ned. Otherwise, when
*converted back again, the result shall compare equal to the original
*pointer."

You are actaully correct, because of that that phrase "correctly aligned".
As you say, it is a bit under-specified. At the moment all pointers consist
of hardware (1)address plus, occasionally, alignment bits to implement
sub-hardware byte chars. That might change because of technical developments
in the future, though I couldn't think of an obvious scenario.
(1) for the pedants, sometimes a translated hardware address.
Jan 13 '07 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

73
by: RobertMaas | last post by:
After many years of using LISP, I'm taking a class in Java and finding the two roughly comparable in some ways and very different in other ways. Each has a decent size library of useful utilities...
3
by: Roubles | last post by:
Hi All, Here's my problem, I have a bunch of code that passes an allocated object (say obj) to a function, and then dereferences that allocated object when the function returns: foo(obj);...
6
by: lovecreatesbeauty | last post by:
Hello experts, 1. Does C guarantee the data layout of the memory allocated by malloc function on the heap. I mean, for example, if I allocate a array of 100 elements of structure, can I always...
3
by: Nadav | last post by:
Hi, I am writing a mixed mode application, I have a mixed mode Assembly manipulating a managed byte array, to access this array in unmanaged code I '__pin' the array, As I understand, pining an...
4
by: gbostock | last post by:
I'm working on some legacy code and came across something like this. Anybody know exactly what the ramifications are to the memory if you do something like this: int somefunction (some...
74
by: ballpointpenthief | last post by:
If I have malloc()'ed a pointer and want to read from it as if it were an array, I need to know that I won't be reading past the last index. If this is a pointer to a pointer, a common technique...
26
by: Bill Reid | last post by:
Bear with me, as I am not a "professional" programmer, but I was working on part of program that reads parts of four text files into a buffer which I re-allocate the size as I read each file. I...
28
by: hijkl | last post by:
hey guys anything wrong with this code?? if it is then what? int *array(int n){ return new int(n); } int main(){ int *p = array(10); for( int i = 0; i < 10; i++ ) {
11
by: xicloid | last post by:
I'm trying to write a program that saves numbers without any duplications. I was thinking I could start by storing the first number in an array with size one, and if the next number is not in the...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.