Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
What is purpose of using sizeof using malloc in C?
Why its necessary?
I mean we can use sizeof but we already know the size(=1000 bytes) what we are allocating in memory?
I am beginner in C so. This might be a very obvious question.
DataTypes And Memory Matter
The answer is in the data types. While you know how many objects you want to allocate memory for, you may not want to go through the trouble of mentally computing their size.
So Does Maintainability
Also, what if the composition of these changes later? Then you're screwed and have to edit everything.
So that's irrelevant in your example, without context. But in the case where you want to allocate memory for more complex things (say, a struct with a number of fields), it does become quite important and useful.
Example 1 (not so important here):
char *s = malloc(100 * sizeof(char));
But hey, it's just chars, it's fine, you could have done that:
char *s = malloc(100);
Generally works. But shooting yourself in the foot, as you'll see below.
Example 2 (matters a bit already):
int *i = malloc(100 * sizeof(int));
Sure, you could have written that:
int *i = malloc(100 * 4);
That is, assuming you develop for just one architecture you know pretty well.
Example 3 (starting to matter quite a bit!):
typedef struct s_listelement{
int dataitem;
struct s_listelement *link;
} t_listelement;
t_listement *le = malloc(sizeof(t_listelement));
Now imagine that linked-list item's structure contains a bunch of other fields...
Would you want to trust sizeof(), or go have fun and do the math yourself?
Suppose you want to allocate memory for storing ints. Your initial guess will be, okay I need to have n integers and each integer requires x bytes. So space will be n*x bytes.
But actually this x depends on architecture. It maybe 16 bit, 32 bit, etc. So to make your code able to work in different environments, it is recommended to use n*sizeof(int) instead of n*x.
For example, if you need to allocate space for 10 integers:
int *p=malloc(sizeof(int)*10);
What happens if you change the size of mallocated?
You will have to 1) calculate again the new size (letting aside multiple target architectures problems, where you will have to calculate the new size in each target), 2) search for all malloc(1000), make sure it refers to mallocated (which might be not obvious) and replace with new size.
You don't have any of these 2 problems using sizeof. Thus using sizeof leads to a more maintainable and readable code.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm researching the possibility of porting a C program over to Rust.
Is it possible to duplicate this C code in Rust?
struct myStruct {
int var1;
int var2;
char var3[32];
int var4;
}
int main() {
struct myStruct myArray[1000];
bzero((char*) myArray,sizeof(myArray)); // clear entire array
myArray[0].var1 = 42;
sprintf(myArray[0].var3, "Hello World!");
/* other code here */
}
I've tried various methods and all come up with compile errors.
As your struct is trivially copyable and only contains types whose default value would be 0, you can simply derive Default and use an array literal:
#[derive(Copy, Clone, Default)]
struct MyStruct {
var1: i64,
var2: [u8; 32],
var3: i64,
var4: i64,
}
fn main() {
let array = [MyStruct::default(); 1000];
}
A structure that is 0-initializable with bzero is most likely always going to be Copy so you can use an array literal.
Note however that this is very likely going to be unidiomatic in Rust, where using Vec would probably be considered better, as explained in bk2204's answer.
Instead of allocating a large array and zeroing items, it may be better to use something like a Vec and insert items into it as you create them. Rust doesn't generally use the zero-initialized structure philosophy, so you'll be able to create items as you need them, and you'll be guaranteed that only valid items are stored in your structure. While it's common in C to stuff uninitialized or partially initialized data into a data structure, Rust prefers to have only fully initialized, valid data, which helps preserve safety guarantees.
You may want to have your structure have a constructor to ensure it's fully initialized, plus accessors. Or, if you aren't exposing the structure to other code, you can just manually initialize it.
If you know well how many items you need to allocate up front, you can use Vec::with_capacity to perform the allocation up front. This can be helpful even if your estimate is a little too low, since the structure can expand at runtime, just less efficiently. Depending on your allocation behavior, a VecDeque could be beneficial instead, but with the downside that you can't convert it into a slice.
If your data structure is more like a hash map or a set, whether sorted or not, then there are collections under std::collections which will likely meet your needs better.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have created a function my_hton() to convert data in host byte order to network byte order. It converts object of any arbitrary structure. If it is correct, why does C has functions like htons() and htonl() which converts only 2 and 4 bytes respectively, instead of having one function for all data types, or am I missing something?
void my_hton(char *buffer, char *p, size_t i){
if( is_little_endian() ){
while(i > 0){
*buffer = p[i-1];
buffer++;
i--;
}
}
}
struct demo{
int a;
char b;
char str[100];
float f;
double d;
int *ptr;
};
int main() {
char buffer[10000] = "";
struct demo object;
/*
* object initialization
*/
my_hton(buffer, (char*) &object, sizeof(object));
return 0;
}
What you have done in your code is flipped the entire structure byte wise, which would cause your individual members to be garbled.
A better question is why would you want to convert the endian ness of an entire structure?
It makes sense to change the endian ness of individual integer type fields, but that needs the information about the fields and hence you cannot have a generic function.
On the other hand if your structure has fixed size elements with equal padding, then you can write a generic function which can convert the endian-ness of each field. But I believe most structs made for network are packed and such cases would be very rare.
You can't do that in general (because structure fields have padding and alignment in addition of endianness for scalars), notably because C has no type introspection or reflection facilities. Also, it is unclear what should be done for pointers or unions or flexible array members in general.
Read more about serialization.
You might consider customizing some C compiler (e.g. extending GCC with MELT or your own plugin) to assist you in that serialization task. I don't think it is worth the effort.
However, some frameworks are adding such facilities. Look for examples into GTK Gobject introspection. Also look into C code generators like
RPCGEN or SWIG. Consider binary formats like XDR, SMILE, ASN1, etc.
In many cases, it is more convenient (even if slightly slower, but the bottleneck is often the network or the disk, not the CPU, so you won't even notice in most cases) to use some textual format like JSON, YAML, XML, .... because text protocols are very common and much easier to debug. You'll find many libraries to help you using these formats.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I know that we cannot dereference a void pointer until and unless we typecast it.
void *ptr = call_a_function();
printf("%d",*(int *)ptr);
This informs the datatype of element(in this case its integer) to the compiler so that it can dereference the amount of space required for it(in this case its 4 bytes).
Suppose I dont know the final datatype, however I know the size of datatype. Can I still dereference it using only the size(4 bytes) and not the datatype(not using int)??
In other words is there a way to tell the compiler how many bytes of memory to read by providing the number of bytes to extract and not the datatype??
EDIT -
I needed to swap the contents of two void * pointers.
Got influenced by the regular way of swapping two values i.e storing the value of one pointer in a temporary variable and then proceed with swapping.
Was trying to attempt the same thing without knowing the datatype but only its size( since the function with this swap code accepts size of variable as one parameter ). However after reading the answers and comments, got to realize that I really dont need to dereference it. Probably memcpy is the correct way to go.
Suppose I dont know the final datatype, however I know the size of datatype. Can I still dereference it using only the size(4 bytes) and not the datatype(not using int)??
Since you cannot deduce or assume the data type, you can't dereference the pointer once to get the complete object. However, you can extract each byte and use it anyway you want.
void *ptr = call_a_function();
unsigned char* cptr = (unsigned char*)ptr;
for (int i = 0; i < num_bytes; ++i )
{
unsigned char c = cptr[i];
// Use c
}
In this case, the whole is not the sum of its parts. Casting not only provides the compiler with the size of the data but also how that data is to be interpreted. Suppose you get 4 bytes, this could be a string of three characters with a NULL byte or a signed integer, which could be encoded in big-endian or little-endian depending on the platform. So knowing the size is not sufficient to properly handle the data even if you could tell the compiler how many bytes to read/dereference.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
EDIT
i want to create a program which will work with a long number. the user will be asked to input the length (in digits) of the number they want to work with. there is a
char aa [the chosen length goes here];
where in the [] brackets should be the value that was input by the user.
it could look like this:
"please input the length in digits"
there is a scanf and you input, for example, 17
then a char aa [17] is created
i just don't know how can i use a variable to input a value in the [] brackets defining the memory size that is saved for a char
You want a variable lenght array, you can do it like this:
int digit;
scanf("%d", &digit);
char test [digit+1];
This will work for your purposes. Usual restrictions of course apply.
Keep in mind this functionality was only added in the C99 Standard. So if your compiler supports only previous standards, this will not work.
However, the more appropriate and better practice method to use is to use malloc to allocate the char array properly
int digit;
scanf("%d", &digit);
char* aa = malloc(digit + 1);
//Do what you want with the char array aa
free(aa);
Do not forget to check the result of malloc() against NULL and free the variable afterwards to prevent memory leaks if you want to do this.
Also be aware that the "array" malloc returns is actually just a pointer, which is very relevant when trying to determine the size/length of it, using sizeof:
char real_array[5];
sizeof(real_array); // == 5
char* dynamic_array = malloc(5);
sizeof(dynamic_array) // == sizeof(char*) == on most systems = 8
What you are asking is variable length array which is possible in C99. See Dynamic array allocation on stack in C
Look at the following code snippet:
int size;
scanf("%d", &size);
char array[size + 1]; //1 extra space to accommodate `\0` character
printf("%d\n", sizeof(array));
This will print sizeof(char) * (size+1) proving the array creation dynamically.
The only disadvantage of this way over malloc way is after declaring an array (which is of user-input size) you can't change the array size in program. It's fixed.
While using dynamic memory allocation (malloc, calloc) you can change the array size whenever possible in a program by freeing the memory.
Since variable length array is possible in c99 you may have to use gcc --std=c99 -c program.c to compile your source code. For other compiler refer the proper compiler manual.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
This is from the perspective of someone on a Linux x86 system. Is it possible to store something other than a hardcoded address in a pointer? Here's the catch though: the value going to be stored in the pointer will have previously been stored as a string. Pretty sure there isn't a way for me to reference any register or other pointer but I just wanted to be sure. And I know people are going to ask why I want to do something like this; it would take too long to explain and I'm absolutely sure there is no alternative solution.
Sould have added this:
char* addresses = "\x32\x45\x19..."
I want to store something other than a hardcoded address in the "addresses".
EDIT:
lol wow I thought I was fairly clear. I have a array of characters, a pointer, or as I call it: a string. This string is going to be treated as a ZVAL struct in PHP. I am wondering if I can store information other than hardcoded addresses within the string.
If the address is stored as a string, you can convert the string to an address (probably via uintptr_t defined in <stdint.h> or <inttypes.h>). You take the bytes in the string and shift and mask them to produce the integer value equivalent to the address, and then assign the address to the pointer.
char *addresses = "\x32...";
char *string = addresses;
uintptr_t value = 0;
for (i = 0; i < sizeof(value); i++)
value = (value << 8) | (*addresses++ & 0xFF); // Sign extension avoided
void *memory_location = (void *)value;
I'm assuming the first byte in the string is the MSB of the address; if (given that you're on Intel) this is wrong (LSB is stored first), you have to adapt the loop to reverse the ordering — one of those infamous 'Exercise for the Reader' observations.
Or you play fast and loose and make the chip do the work. On RISC platforms (non-Intel), this would lead to a SIGBUS error in general; you might get lucky some of the time, though.
char *addresses = "\x32...";
void *memory_location = (void *)(*(uintptr_t *)addresses);
This tells the code to treat the char * as if it were a uintptr_t *, dereference it (reading the whole string at once, except if the address is not properly aligned, it will be two fetches, maybe with a kernel trap in the middle), and assign the value to the memory location.
If your code has any pretense at portability, make sure this is in the 'non-portable code' section.
This is a technical solution to the problem posed (as I understand it); it is not a recommendation that you use it.
you said "lol wow I thought I was fairly clear. I have a array of characters, a pointer, or as I call it: a string. This string is going to be treated as a ZVAL struct in PHP. I am wondering if I can store information other than hardcoded addresses within the string."
Not in the way you do it.
char * addresses = "\x32\x45\x19..." ;
addresses is set to point to something you should not change.
you need to allocate storage for that stuff.
e.g.
char stuff [256] ;
char * addresses = stuff;
memcpy(stuff,"\x32\x45\x19...",sizeof("\x32\x45\x19..."));