I have allocated array of void
I need to acces bytes of allocated memory
void* array = (void*) malloc(12);
array[0] = 0;
It returns me this error:
main.c:9: error: invalid use of void expression
array[0] = 0;
^
Is there any way how to do it ?
Thanks!
Your array is a void-pointer. And void (in C) means 'has no type'. So when you dereference it (like array[0]) the compiler has no idea what that means.
To access bytes you need a char type, which is actually the C-equivalent of a byte (a remnant from the days when characters would still fit into (8-bit) bytes).
So declare your array as:
char * array = malloc(12);
Also note that you don't have to cast the result of malloc (especially in your case since it already returns a void *). And, if you want just the 12 bytes and only use them locally (within the function or translation-unit that declares it) then you can just use a 'proper array':
char array[12];
This has the added bonus that you don't need to free it afterwards.
You need to use char or unsigned char rather than void to access the bytes:
char *array = malloc(12);
array[0] = 0;
malloc() returns a void pointer because it doesn't know the type you're allocating. You can't access the memory via that void pointer; you need to tell the compiler how to treat the block of memory. To treat it as bytes, use char or unsigned char.
Related
char **three = (char**)malloc(sizeof(char*));
char**, the char pointer type is used. and char** means I'm dereferencing char pointer. and as for the sizeof(char*) I'm using the size of char pointer which is 8 byte.
Am I misunderstanding this?
So the code:
char **three = ( char** )malloc( sizeof( char* ) );
Allocates an array of pointers-to-char, but with only a single element. The variable three is a pointer-to, a pointer-to a char. Much the same as:
char *three[1];
Normally (as #paxdiablo points out), it would be more usual to allocate a number of pointers:
int line_count = 66;
char **three = ( char** )malloc( line_count * sizeof( char* ) );
Once allocated, this can be used with array notation:
three[0] = "The Owl and the Pussy-cat went to sea";
three[1] = "In a beautiful pea-green boat,";
three[2] = "They took some honey, and plenty of money,";
three[3] = "Wrapped up in a five-pound note."
There's nothing particularly special about a char**, every C/C++ program gets one as its argv.
As a programmer, you don't really know that your pointer is 8 bytes, you know the pointer will be some size. This is where the sizeof( char* ) comes in. During compilation the compiler swaps this with the real value. That way when the architecture is 16, 32 or 64 bit (or maybe 128 bit in the future), the code still compiles fine.
Let's see if we can break this down:
char **three = (char**)malloc(sizeof(char*));
[ 1 ][5][ 4 ][ 3 ] [ 2 ]
Create a variable three of type char **, a pointer to a char * (often a "string" in C).
Use the size of a char* to pass to malloc.
Use malloc to allocate that many bytes.
Cast the return value from malloc, a void*, to char**.
Assign that value to three.
So in terms of where I think your misunderstanding lies:
Do not cast the return value of malloc or realloc in C. C is perfectly capable of implicitly casting void* to other pointer types and doing it explicitly can hide certain subtle errors.
There is no dereferencing going on here. The (unwise) cast is exactly that, telling the compiler you want to treat an expression of one type as if it was another type.
You've actually allocated an array of char* variables and that array size is one. So, short of calling realloc on it at some point, its use is limited (unless you need it to survive the current scope, you're probably just better using a local variable rather than an allocated one-element array).
malloc() function is said to return a null pointer or a pointer to the allocated space. Suppose for a string we make the statement:
char* ptr = malloc(size)
Isn't ptr a pointer that would point to a pointer?
Isn't :
char** ptr = malloc(size)
supposed to be the correct way to declare the pointer to char?
The compiler however doesn't give a warning when we do either, the warning it does give is for the format specifier if used.
How should we declare this and why? Also, how would char** be used?
No, 'ptr' would contain the pointer returned by 'malloc'. You are assigning the returned pointer, not taking its address.
The char * denotes a char pointer. Malloc will return a void * pointer (that will be automatically converted to whatever pointer you're trying to assign).
The char ** denotes a char * pointer. This is a pointer to a pointer.
If you think of a pointer as a map you have that char * is a map to a char, void * is a map to something mysterious and char ** is a map to another map that leads to a char. So
char* ptr = malloc(size);
Is the correct one, because you want a map to something, not a map to a map.
*ptr is a pointer to a char, which is often used to manage an array
or a string.
**ptr is a pointer to a pointer to a char, which is often used to
manage a matrix (array of arrays) or a string array.
for (int a=0; a<10; ++a) {
printf ("%d", a);
}
char *foo;
foo = (char*)malloc(a);
I want to store more than one char value in foo variable.
Should I change it to an array, since the buffer is only allocating 1 char length?
Is 1 the longest length that can be stored in this buffer?
Well, foo now points to some useable address of a bytes, because this is how malloc() works. It doesn't matter if its type is char *, void * or anything else, you can only use a bytes.
Here, you increment a to 10. That means you can store 10 bytes, being 10 chars, (because in the context of C, 1 char = 1 byte), starting at the address where foo points to. Using a pointer or an array is strictly equivalent.
Since the buffer is only allocating 1 char length...
No, it is not the case here.
Quoting from the C11 standard, chapter §7.22.3.4, The malloc function
void *malloc(size_t size);
The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
So, in case of
foo = malloc(a); //yes, the cast is not required
a memory of size same as the value of a will be allocated, considering malloc() is successful.
Simply put, if I write a snippet like
int * p = malloc(10 * sizeof*p);
then, I can also write
for (int i = 0; i < 10, i++)
p[i] = i;
because, I have allocated the required memory for 10 ints.
That said, please see this discussion on why not to cast the return value of malloc() and family in C..
There are a couple of things you could do in a case like this.
If you know at compile time how many chars you want to store you could make it an array char foo[10]; If you know that there is always going to be 10 (or less) characters you want to store.
If you are not sure how many chars it needs to hold at compile time you would typically do dynamic allocation of memory using malloc. Now when using malloc you specify how many bytes of memory you want so for 12 chars you would do malloc(12) or malloc(12 * sizeof(char)). When using malloc you need to manually free the memory when you are done using it so the benefit of being able to ask for arbitrary (within limits) sizes of memory comes at the cost of making memory management harder.
As a side note: You typically do not want to cast the return value of malloc since it can hide some types of bugs and void *, that malloc returns can be implicitly cast to any pointer type anyway.
Example
#include <stdio.h>
struct A {
char *b;
};
int main(int argc, char *argv[]) {
char c[4] = { 'c', 'a', 't', '\0' };
struct A a;
a.b = c;
printf("%s\n", a.b); // cat
printf("%lu\n", sizeof c); // 4
printf("%lu\n", sizeof a.b); // 8 ???
}
Why does sizeof a.b returns 8 and not 4? If I understood correctly, a.b returns the value that was assigned to it, which is c. But shouldn't it return the size of c (which is 4) then?
sizeof() operator gives the number of bytes allocated to the object and in your case the object is a pointer whose size looks like is 8 bytes on your system.
You're calling sizeof() on two different types.
sizeof(a.b) is sizeof(char *), which is 8 on your platform.
sizeof(c) is sizeof(char[4]), which is 4.
We can have pointers point to arrays via array decaying, which you can read about in this other answer: What is array decaying?
First of all sizeof(a.b) is not size of c. It doesn't give size of what it is pointing to, rather it is size of the pointer.
Take an example of char:
size of char a is 1
and char *b is 4. (on 64 bit)
So it is size of the pointer not what it points to. Please note these sizes are platform dependent.
Although don't get confused by int. An int and int * are of same size on some platforms.
If I understood correctly, a.b returns the value that was assigned to it,
Not exactly. a.b is what's called an lvalue. This means that it designates a memory location. However it does not read that memory location yet; that will only happen if we use a.b within a larger context that expects the memory location to be read.
For example:
a.b = something; // does not read a.b
something = a.b; // does read a.b
The case of sizeof is one context where it does not read the memory location. In fact it tells you how many bytes comprise that memory location; it doesn't tell you anything about what is stored there (let alone about some other memory location that might be pointed to by what is stored there, if it is a pointer).
The output is telling you that your system uses 8 bytes to store a pointer.
sizeof() returns the number of bytes of a variable.
In this case sizeof ( char * ) returns 8 bytes which is the number of bytes that compose a pointer.
Recently, I am trying to make good practice on C now I come to a command execution.
It tells me that I should us char**? But am I have some concept wrong.
Please help me.
Code is here
int excution(int cnt, char token[][BUFSIZE],int *t_token)
{
setenv ("PATH", "/bin:/bin/usr:", 1);
//printf("%s",getenv("PATH")); // check environement
const char *b_cd="cd";
const char *b_exit="exit";
const char *b_fg="fg";
const char *b_jobs="jobs";
int i,j,k;
//STEP 9:excute normal commanand
char args[cnt][BUFSIZE];
for(i=0;i<MAXARG;i++)
{
if(t_token[i]==COMMAND)
{
strcpy(args[0],token[i]); // copy 1st ARG
j=1;
while(t_token[i+1]==ARG)
{
strcpy(args[j],token[i+1]);
i++;
j++;
}
for(k=0;k<j;k++)
{
printf("%s\n", args[k]);
}
execvp (args[0], args);
}
}
It gives me warning in compilation. But it gives segmentation fault if I change 2D array to a char**....
warning: passing argument 2 of ‘execvp’ from incompatible pointer type
[enabled by default] /usr/include/unistd.h:579:12: note: expected
‘char * const*’ but argument is of type ‘char (*)[256]’
Maybe I'm just old, but when I see char var[X][Y] I think the compiler is going to allocate a chunk of memory of sizeof(char)*X*Y and then var[i] will be equal to var+(i*Y*(sizeof(char))). As long as everybody knows what X & Y are, all is cool. But execvp() doesn't know your X & Y sizes.
In contrast, char * var[X] will give me an array of X pointers each sizeof(char*), or a blob of memory of sizeof(char*)*X.
Now char's are generally 1 byte. char* is generally 4 or 8 bytes, but can vary depending on your system.
So char * var[X] might be a chunk of memory X*8 bytes in size, and anyone receiving var as an argument would know how to access each char* pointer in that array as pointer sizes are well known by the compiler and it's just a standard offset.
On the other hand, anyone receiving char var[X][Y] is going to be really confused. There's no way to tell where one argument ends and another begins in that giant chunk of memory.
Long story short: Use char * args[SIZE];, use arg[i] = "command" or arg[i] = token[j], and learn about pointers.
p.s. char** is a pointer to a pointer to char. (It's, say, 8 bytes that points to another memory address of 8 bytes of data that contains the memory address of a char (1-byte) value. This makes more sense when we talk about storing strings as null-terminated (char(0)) arrays of characters - e.g. sequentially stored characters, so if we know the address of the first character in the string we can just increment the pointer to get the next character until we hit zero, the null character '\0'.)
It's similar to, but not quite the same as an array of pointers to char. (Which is, say, 8 bytes that points to a memory address containing at least 8 bytes of data, perhaps N*8 bytes of sequential memory addresses (pointers). Again, just like with the sequential char array, we can have an array of char*, one stored after the other in memory.)
It would be more accurate to say a char** is roughly equal to a char*[N], only the char** doesn't allocate any memory for the internal char* pointers whereas char*[N] does - it allocate space for N char* pointers.
When receiving an array of pointers to char (char*[]), you can declare it as a pointer to a pointer to char (char**) and still iterate through the array. You just need to have the right underlying block of memory (data) located (passed in) where that pointer points to.