I have to implement a function that returns the memory address of a pointer when I allocate it with malloc(). I know that malloc(value) allocates an area on the heap which is of size value.
I know how to implement the code for printing the memory address of that pointer:
void *s = malloc (size)
printf("%p\n",s);
My question is, how can I save the value printed by that code in an int or string (e.g. char *)?
Storing the value of the pointer (i.e. the memory location of some variable) in a string can be done much like you've used printf:
char buf[128];
void *s = malloc (size);
sprintf(buf, "%p\n",s);
To 'save' the value into an integer (type) you can do a simple cast:
void *s = malloc (size);
size_t int_value = (size_t)s;
Since in c you never know what your machine address pointer length is, this (technically) isn't guaranteed to work quite right; both of these methods can go wrong with wacky architectures or compilers.
char buf[32] = {0}
snprintf(buf, sizeof buf, "%p\n", s);
then you can print it:
printf("%s\n", buf);
You've already saved the value as a bit pattern in s, so I assume you mean that you simply want the text output by printf as a string. The call you want is sprintf:
char text[255];
sprintf(text, "%p\n", s);
If you want the pointer address returned from your function, you can declare your function to return the pointer type:
int* myFunc(int n) {
int* p;
p = malloc(n*sizeof(int));
// more stuff
return p;
}
This is an alternative to the use of sprintf as suggested (very reasonably) by other answers.
Take your pick.
Note that on some systems an int would not be big enought to hold a int* data type - using int* is not only clearer but safer as well.
Yes sprintf() is the best option. Here you can simply take any thing inside a string.
Related
I am studying the C language.
When I pass a pointer to gets(), I find it can work well.
char *ptr;
gets(ptr);
puts(ptr);
But if I define an array of pointers, it doesn't work.
char *ptr[4];
int i=0;
for(i=0;i<4;++i)
gets(ptr[i]);
for(i=0;i<4;++i)
puts(ptr[i]);
Are they different, or is the first part wrong in fact? I want to know the reason.
You pass a pointer to a function (e.g. gets()) that writes data to a memory location pointed by your pointer. In your case, you have the uninitialized pointer, which means it points to a random memory location (where applications or an operating system resides). This leads to random effects - from "working" to abnormal termination or hanging. You need to reserve memory and assign pointer to point there, e.g. by:
char *ptr = (char*)malloc(256);
gets(ptr);
puts(ptr);
free(ptr);
Consider to use gets_s() that is more secure.
char *ptr[4];
int i=0;
for(i=0;i<4;++i)
gets(ptr[i]);
This is not valid C code as you did not allocate space for ptr[i]. On the other hand, never use gets because it's a function that does not check for buffer limit.
The pointer has to point somewhere first.
#define BUFSIZE 100
char *ptr = malloc(BUFSIZE);
fgets(stdin, ptr, BUFSIZE);
puts(ptr);
char *ptr[4];
int i=0;
for(i=0;i<4;++i) {
ptr[i] = malloc(BUFSIZE);
fgets(ptr[i], BUFSIZE, stdin);
}
for(i=0;i<4;++i) {
puts(ptr[i]);
}
I have declared a string and using malloc function I allocated the memory... Now I want to change this string into a floating type.
char *str;
str=malloc(sizeof(char)*10);
strcpy(str,"123.4");
float i=strtof(str, NULL);
Now I don't want to use a new variable 'i' instead, I want to store it in str itself. It is required for me to access data from 'str'
1. Is it possible ??
2. If not suggest a better solution or indirect method.
Please answer 1st question clearly.
Since the pointer returned by malloc() is sufficiently well aligned to be used as a pointer to any type, you could (but probably shouldn't) use:
assert(sizeof(float) <= 10);
void *data = malloc(10);
char *str = data;
strcpy(str, "123.4");
float *vp = data;
*vp = strtof(str, NULL);
…use *vp…
free(data);
And now you can use *vp for the float value. However, that's ridiculous compared with:
char *str = malloc(10);
strcpy(str, "123.4");
float value = strtof(str, NULL);
…use value…
free(str);
which is basically your original code — that you decided for unclear reasons was not what you wanted to do.
There is a way to do it, but it's ugly, unsafe, may not work as expected, and is most definitely not recommended.
You can treat the first sizeof (double) bytes of the memory pointed to by str as a double1:
*(double *)str = strtod( str, NULL );
Basically, we're treating str as the address of a double object and assigning the result of strtod to it. To access that double value, you'd need to cast again:
printf( "value stored in str = %f\n", *(double *) str );
Now, this means we've overwritten the first sizeof (double) bytes of the string with the double value, so you've lost the original string value. If you need to preserve the original string value while also treating it as a floating-point value, then you have to use separate objects to do so. C isn't Python or Javascript, and values don't magically change their representation based on context.
Unless you're really constrained on memory or have a specific reason to use float, use double instead. This also means you need to make sure the memory you allocate is at least sizeof (double) bytes wide.
You can use union for that.
union mytype {
char * str;
float f;
};
I am working on a short program that reads a .txt file. Intially, I was playing around in main function, and I had gotten to my code to work just fine. Later, I decided to abstract it to a function. Now, I cannot seem to get my code to work, and I have been hung up on this problem for quite some time.
I think my biggest issue is that I don't really understand what is going on at a memory/hardware level. I understand that a pointer simply holds a memory address, and a pointer to a pointer simply holds a memory address to an another memory address, a short breadcrumb trail to what we really want.
Yet, now that I am introducing malloc() to expand the amount of memory allocated, I seem to lose sight of whats going on. In fact, I am not really sure how to think of memory at all anymore.
So, a char takes up a single byte, correct?
If I understand correctly, then by a char* takes up a single byte of memory?
If we were to have a:
char* str = "hello"
Would it be say safe to assume that it takes up 6 bytes of memory (including the null character)?
And, if we wanted to allocate memory for some "size" unknown at compile time, then we would need to dynamically allocate memory.
int size = determine_size();
char* str = NULL;
str = (char*)malloc(size * sizeof(char));
Is this syntactically correct so far?
Now, if you would judge my interpretation. We are telling the compiler that we need "size" number of contiguous memory reserved for chars. If size was equal to 10, then str* would point to the first address of 10 memory addresses, correct?
Now, if we could go one step further.
int size = determine_size();
char* str = NULL;
file_read("filename.txt", size, &str);
This is where my feet start to leave the ground. My interpretation is that file_read() looks something like this:
int file_read(char* filename, int size, char** buffer) {
// Set up FILE stream
// Allocate memory to buffer
buffer = malloc(size * sizeof(char));
// Add characters to buffer
int i = 0;
char c;
while((c=fgetc(file))!=EOF){
*(buffer + i) = (char)c;
i++;
}
Adding the characters to the buffer and allocating the memory is what is I cannot seem to wrap my head around.
If **buffer is pointing to *str which is equal to null, then how do I allocate memory to *str and add characters to it?
I understand that this is lengthy, but I appreciate the time you all are taking to read this! Let me know if I can clarify anything.
EDIT:
Whoa, my code is working now, thanks so much!
Although, I don't know why this works:
*((*buffer) + i) = (char)c;
So, a char takes up a single byte, correct?
Yes.
If I understand correctly, by default a char* takes up a single byte of memory.
Your wording is somewhat ambiguous. A char takes up a single byte of memory. A char * can point to one char, i.e. one byte of memory, or a char array, i.e. multiple bytes of memory.
The pointer itself takes up more than a single byte. The exact value is implementation-defined, usually 4 bytes (32bit) or 8 bytes (64bit). You can check the exact value with printf( "%zd\n", sizeof char * ).
If we were to have a char* str = "hello", would it be say safe to assume that it takes up 6 bytes of memory (including the null character)?
Yes.
And, if we wanted to allocate memory for some "size" unknown at compile time, then we would need to dynamically allocate memory.
int size = determine_size();
char* str = NULL;
str = (char*)malloc(size * sizeof(char));
Is this syntactically correct so far?
Do not cast the result of malloc. And sizeof char is by definition always 1.
If size was equal to 10, then str* would point to the first address of 10 memory addresses, correct?
Yes. Well, almost. str* makes no sense, and it's 10 chars, not 10 memory addresses. But str would point to the first of the 10 chars, yes.
Now, if we could go one step further.
int size = determine_size();
char* str = NULL;
file_read("filename.txt", size, &str);
This is where my feet start to leave the ground. My interpretation is that file_read() looks something like this:
int file_read(char* filename, int size, char** buffer) {
// Set up FILE stream
// Allocate memory to buffer
buffer = malloc(size * sizeof(char));
No. You would write *buffer = malloc( size );. The idea is that the memory you are allocating inside the function can be addressed by the caller of the function. So the pointer provided by the caller -- str, which is NULL at the point of the call -- needs to be changed. That is why the caller passes the address of str, so you can write the pointer returned by malloc() to that address. After your function returns, the caller's str will no longer be NULL, but contain the address returned by malloc().
buffer is the address of str, passed to the function by value. Allocating to buffer would only change that (local) pointer value.
Allocating to *buffer, on the other hand, is the same as allocating to str. The caller will "see" the change to str after your file_read() returns.
Although, I don't know why this works: *((*buffer) + i) = (char)c;
buffer is the address of str.
*buffer is, basically, the same as str -- a pointer to char (array).
(*buffer) + i) is pointer arithmetic -- the pointer *buffer plus i means a pointer to the ith element of the array.
*((*buffer) + i) is dereferencing that pointer to the ith element -- a single char.
to which you are then assigning (char)c.
A simpler expression doing the same thing would be:
(*buffer)[i] = (char)c;
with char **buffer, buffer stands for the pointer to the pointer to the char, *buffer accesses the pointer to a char, and **buffer accesses the char value itself.
To pass back a pointer to a new array of chars, write *buffer = malloc(size).
To write values into the char array, write *((*buffer) + i) = c, or (probably simpler) (*buffer)[i] = c
See the following snippet demonstrating what's going on:
void generate0to9(char** buffer) {
*buffer = malloc(11); // *buffer dereferences the pointer to the pointer buffer one time, i.e. it writes a (new) pointer value into the address passed in by `buffer`
for (int i=0;i<=9;i++) {
//*((*buffer)+i) = '0' + i;
(*buffer)[i] = '0' + i;
}
(*buffer)[10]='\0';
}
int main(void) {
char *b = NULL;
generate0to9(&b); // pass a pointer to the pointer b, such that the pointer`s value can be changed in the function
printf("b: %s\n", b);
free(b);
return 0;
}
Output:
0123456789
As in subject of this topic. I have a simple function:
char *to_str(int x)
{
char *s = malloc(6);
if (s == NULL) {
error("malloc");
}
snprintf(s, sizeof(s), "%d", x);
return s;
}
which is allocating memory in its body, and returning such value. How should I handle memory deallocation? What would be the best approach?
How should I handle memory deallocation?
Carefully. And definitely better than you do currently.
What would be the best approach?
The best approach is to free() the memory when you don't need it anymore:
char *str = to_str(1337);
// do stuff with `str'
free(str);
Also, that sizeof() is wrong. It gives you the size of a pointer, not the size of the buffer. You need to keep track of it yourself.
The calling code needs to free the memory using free():
void f(int x)
{
char *s = to_str(x);
// ...
free(s);
}
(By the way, you have a bug: in to_str, sizeof(s) is the size of a pointer, not the length of the string that s points to.)
The first of all, sizeof() is an operator that gives you a length in bytes of type (type of variable) in brackets. Thus instead of actual length of the allocated memory block, you are getting a size of the pointer s, that in common not what you expect.
The second, when you allocating the memory, you should understand the moment when it is not actually used and to make free() on it.
Also, I am not sure that 5 symbols + terminating 0 is an enough length of the string, as in case of the garbage in the x the string will be much longer, so you can corrupt the memory.
The best is not to allocate memory inside function:
char* to_str(char *buffer, size_t buffer_size, int x);
this way you don't have to care about deallocation inside the function and everything is on the caller side.
If you want to create function with the signature you have in the question, you cannot use that in anything like printf("%s", to_str(x)), because this would be a memory leak. You have to make char *str = to_str(x); printf("%s", str); free(str); which is not nice...
There are four ways to dynamic allocate memory, is there differences among the four ways?
first like this:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
// using 'seq'
}
second like this:
char *seq;
void exam(char *seq){
seq=(char *)malloc(100*sizeof(char));
// using 'seq'
}
third like this:
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *seq){
char *change=(char *)malloc(100*sizeof(char));
free(seq);
seq=change;
// using 'seq'
}
fourth like this:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
free(seq);
seq=(char *)malloc(100*sizeof(char));
//using 'seq'
}
and you should konw that, I will use the variable 'seq' outside of the method 'exam'.
please explain the above codes, thank you very much.
Only the first case is valid if you intend to use seq outside of exam.
The other three cases receive the address allocated for seq, but are unable to change it.
To change the value of seq, you need to either return a new value for it, or explicitly modify what's in seq.
You need to investigate Pass by Value to understand why this doesn't work. See this page.
You should not cast the result of malloc() unless you're using an implementation of C that predates the 1989 ANSI standard, or you intend to compile this code as C++, in which case you should be using new instead of malloc(); first of all, it isn't necessary, and second of all, it will mask a compiler diagnostic if you don't have a prototype for malloc() in scope.
Also, sizeof(char) is 1 by definition; using it in this case makes no difference and just adds visual noise.
The canonical form for writing a malloc() statement for any type T is
T *p = malloc(count * sizeof *p);
or
T *p;
...
p = malloc(count * sizeof *p);
Now addressing your four cases...
Your first case is generally correct; you're allocating the memory for seq outside of exam, and passing the pointer by value.
Your remaining cases all have a similar problem; the change to the pointer value seq is not going to be reflected in the caller, and you will have introduced a memory leak. If you're passing a pointer to a function, and you want the pointer value to be overwritten, then you need to pass a pointer to that pointer:
char *seq;
exam(&seq);
...
void exam(char **seq) { *seq = malloc(100); ... }
If you want to resize a dynamically allocated buffer, use realloc():
char *seq = malloc(10);
exam(&seq);
...
void exam(char **seq)
{
char *tmp = realloc(*seq, 100);
if (!tmp)
{
/* realloc failed */
}
else
{
*seq = tmp;
...
}
Note that
char *p = realloc(NULL, 10);
is the same as
char *p = malloc(10);
There are probably many ways to do what your doing. If you intend on using seq outside of the function, the first method you outlined will work.
The other methods you have have other issues if you intend on using seq after calling the function. Since C is pass by value, you are passing the address contained in seq to the routine, which will not change the memory location associated with seq in the last three examples. To change the memory location of seq, you need to pass the address of the pointer into the routine to set the pointer. This is shown in David Cournapeau example.
The issue with the last two cases is that you "freed" the memory, but you are still retaining a pointer to the memory as the value of seq will not be changed and you can use it to access memory you have "freed". This is known a a dangling pointer.
David Cournapeau suggestion of using a function to return the pointer would give you access to the memory you allocated in the function. Otherwise you will need to pass the address of seq into the routine and dereference the value to set it to the allocated space.
It all depends on what you are trying to do. If possible, it is better to do malloc/free in the same scope, IMO, it makes the code much more readable - memory allocation in C is already hard enough. In your case, you would first malloc, call the function, and free after outside the function. But of course, it is not always possible.
Some of your solutions will not work: the second one, for example, will not do what you want, because when you call the function, the pointer is copied:
char *p;
function(p);
void function(char *q) {
// q is a copy of p, so when q is set by malloc, it will not be reflected in p
q = malloc(100);
}
Generally, you should do as the fopen functions: you return a pointer:
char* p function() {
char* ret;
ret = malloc(100);
return ret;
}
char *p = function();
Or you could use a pointer to a pointer:
char *p;
function(&p);
void function(char **q) {
// q is a copy of &p, so when *q is set by malloc, it is the same memory location as &p
*q = malloc(100);
}
I think the first one is much better, though, in general.
Also, concerning your style: sizeof(char) is useless, it is always equal to 1 by definition, whatever compiler/platform you are using, and casting the malloc is useless and actually dangerous (because it hides missing header inclusion where malloc is declared). It is only useful if you use malloc in C++ (where the cast is mandatory).
I think these are differences in scope
To cast some light on the situation, consider this rewriting:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
// using 'var'
}
//--
char *seq;
void exam(char *var){
var=(char *)malloc(100*sizeof(char));
// using 'var'
}
//--
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *var){
char *change=(char *)malloc(100*sizeof(char));
free(var);
var=change;
// using 'var'
}
//--
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
free(var);
var=(char *)malloc(100*sizeof(char));
//using 'var'
}
When you call
exam(seq);
the above versions are identical to your original.