I'm trying to send an encrypted message in a simple server-client chat program.
This is the send() call:
int send(int sockfd, const void *msg, int len, int flags);
Can I pass an int array as *msg?
I think you can use the send() system call. But be aware, that the len is the length of the message in bytes. So i think for an array of 5 int. You need to specify the len as 5*(sizeof(int)).
Additionally, on the receiving side, you need to interpret it accordingly.
As Naveen pointed out, a more detailed answer to your question is already present here.
Yes, you are allowed to pass an array of ints to send(). The reason you're allowed to do that is arrays are automatically converted to pointers when they are passed to functions. See this previous question.
In addition, any pointer in C is can be automatically cast to void * if necessary. Void pointers were designed to provide implicit conversion.
Related
The buffer is something that we declare when we write the program just like we declare an array or is it something that's already in the computer.
List item
If I declare char buffer[MAX_LENGTH],is the buffer ,which I declare ,a buffer?
List item
Book called Pointers On C says the function sprintf() write values to the buffer.This is the function prototype from the book.int sprintf(char*buffer,char const * format,...)Is the buffer in this function prototype a buffer or just an array whose name happens to be buffer?
#include<stdio.h>
#include<string.h>
int main(void)
{
char buffer[50]={0};
sprintf(buffer,"%c%c%c",'a','b','c');
puts(buffer);
return 0;
}
The result is abc.So is the buffer just a ordinary array?Is the buffer here absolutely different with the buffer in I/O?If the buffer here just an ordinary array,then why is the first argument in this function prototype in such a misleading way, instead of just declaring it as char*arr?
Let's try to shed some light on the technical terms. This answer will not be a definition, just the trial to express in simple words, how the terms use commonly used.
An "array" is a sequence of elements of identical data type. Its "size" is the number of elements. Some programming languages allow non-negative numbers including zero, but some require at least one element. Commonly the individual elements are accessed by indexes.
"Array" describes only the data type, but not the intended usage.
A "buffer" is a specialized space used to, well, buffer values. The reason for buffering depends on the usage, for example a function needs readily available space for generated output.
A buffer can be an array, but it also can be a single value.
"Buffer" does not describe a data type, but an intended usage.
The names of parameter shall tell the user the purpose of the parameter. This is true for all names, not only parameter names.
The data type is clear from the specification. It always shows a lack of understanding if a name describes the data type, not the intention.
So, sprintf(char *buffer, const char *format, ...); is quite OK.
In contrast, sprintf(char *arr1, const char *arr2, ...); brings confusion.
buffer is nothing more than a chunk of memory used to store the data. So if you store characters - it will be simply a char array.
If your data has another type, you will need "a simple" array of that type. Example: jf you want to store double you will need array of doubles
Of course, every array of something is just a chunk of memory.
In declaration:
int sprintf(char * restrict s, const char * restrict format, ...);
function sprintf takes pointers to char as parameters, but those pointers simply reference some chunks of memory. You can call them bufferes.
Im trying to implement a function with the following prototype.
int get_next_line(const int fd, char **line) .
The first parameter is the file descriptor that will be used to read.
The second parameter is the address of a pointer to a character that will be used
to save the line read from the file descriptor.
The only thing i know about difference of passing reference and value is that referencing allows you modify the content value.
But for the given prototype, we have the address of the first characters, so i don't fully understand the need for the double pointer.
[Edited] : We store one line of chars inside '**line'.
My question is:
Why use **line and not just *line , or why not ?
int get_next_line(int fd, char **line);
This is a usable function. It presumably allocates a character array of tentatively sufficient size, reads a line into it, reallocates and reads the remainder if necessary, and then passes the allocated string back by assigning it to the dereferenced second argument (*line = allocated_string;).
int get_next_line(int fd, char *line);
This is patent nonsense. There is no way to write get_next_line that is remotely as usable as the previous one. It cannot determine the size of the character array passed to it, nor can it reallocate this array. The only way to specify this function to behave somewhat sensibly is to demand that the argument must be an array of some pre-determined size specified elsewhere. This could only be useful in some pretty narrow contexts.
Note that this is not an immediately obvious observation. The C language used to have gets up until 2011. Programmers used to be rather careless back when.
int get_next_line(int fd, char *line, size_t size);
This could be a somewhat useful function. It could work almost like the standard read function, except it wouldn't read past the first end-of-line character. (Or like fgets for Posix fike handles.) Of course users need to deal with the case of the input line being longer than their array. Presumably get_next_line would return the number if scanned characters.
Note const int is useless in function prototypes. All standard functions specify int in such cases.
I recently wrote a wrapper for LevelDB in C and stumbled about the following problem. The LevelDB function to store data in a database looks like this:
leveldb_put(leveldb_t* db, const leveldb_writeoptions_t* options, const char* key, size_t keylen, const char* val, size_t vallen, char** errptr);
For the key and value, they use a char*. That means I would have to cast arguments that aren't char pointers. This happens often because I often store structs in the database.
After thinking about this I decided to use a void* for key and data in my wrapper function. It then looks something like this:
int db_put(db_t db, void *key, size_t keylen, void *value, size_t valuelen)
{
char *k = (char*)key;
char *v = (char*)value;
/* Call leveldb_put() here with k and v as parameters. */
return 0;
}
This way I don't have to cast the arguments I pass to my db_put() function. I think this solution is more elegant, but I guess LevelDB knew what they were doing when they choose the char pointers.
Is there a reason not to use void* to pass arbitrary data to a function?
Is there a reason not to use void* to pass arbitrary data to a
function?
No. In fact, void * exists to facilitate passing arbitrary data without the need for ugly casting. That's why ptr-to-void was standardized. In C at least. C++ is a different beast.
At LevelDB they have to deal with historical code born with char * , or pre C89 compilers, or any other veiled reason causing refactoring-inertia. Their code would work with ptrs-to-void just as well.
Note that in your version of db_put the casts should be removed as they are redundant.
The current accepted answer exists only to flatter the OP; It's actually slightly invalid.
Consider that your arbitrary struct may (most likely) have padding bytes somewhere. The value of those padding bytes is indeterminate and may or may not be insignificant.
Consider what might happen if you put a struct as key that has padding bytes, and you then attempt to get the value for that key which is otherwise equal except for the padding bytes.
Consider also how you might handle pointer members, if you choose to do so in the future.
If you intend to use a struct as key, it would be a good idea to serialise it, so you can guarantee retrieval of the corresponding value without worrying about those padding bits.
Perhaps you could pass a function pointer telling your wrapper how to serialise the key into a string...
A void* can be considered a black box that holds a pointer. By holding it
in a void* you are effectively saying that you don't care or it contains at that point, so this will allow you to make any assumption about it.
Void* is a "true" generic pointer, and can be directly assign to any particular data type without using cast.
Meanwhile, a char* explicitly specify the type of the respective object. Initially there was no char* and char* was also used to represent generic pointers. When char* is used an explicit cast is required, however the usage of char* as a generic pointer is not recommanded, because it may create confusion, like it did back there when it was hard to tell if a char* contains a string or some generic data.
Also, is legal to perform arithmeticon a char*, but not on a void*.
The downside of using void*, is given by their main usage, they can hide the actual type of the data you're storing, which prevents the compiler and other stuff to detect type errors.
In your specific situation there is no problem in using void* instead of char*, so you can use void* without worries.
Edit: Updated and reformuled the answer to correct some wrong info
You should be serializing to some standard format like json instead of dealing with raw data like that. It looks very error prone unless you always assume that the arbitrary data is just a byte buffer. In which case I would use uint8_t pointer (which is an unsigned char*) and cast all data structures to it so that the routine just thinks that it is dealing with a byte buffer.
A note on void*: i almost never ever use them. Think carefully when you introduce void pointers because in most cases you can do away with the right way of doing things which takes advantage of the standard types to avoid future bugs. The only places where you should use void* is in places like malloc() where there is not really a better way.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
If I need to write a function that returns an array: int*, which way is better?
int* f(..data..)
or: void f(..data..,int** arr)
and we call f like this: int* x; f(&x);. (maybe they are both the same but I am not sure. but if I need to return an ErrorCode(it's an enum) too, then in the first way f will get ErrorCode* and in the second way, f will return an ErrorCode).
Returning an array is just returning a variable amount of data.
That's a really old problem, and C programmers developed many answers for it:
Caller passes in buffer.
The neccessary size is documented and not passed, too short buffers are Undefined Behavior: strcpy()
The neccessary size is documented and passed, errors are signaled by the return value: strcpy_s()
The buffer size is passed by pointer, and the called function reallocates with the documented allocator as needed: POSIX getline()
The neccessary size is unknown, but can be queried by calling the function with buffer-length 0: snprintf()
The neccessary size is unknown and cannot be queried, as much as fits in a buffer of passed size is returned. If neccessary, additional calls must be made to get the rest: fread()
⚠ The neccessary size is unknown, cannot be queried, and passing too small a buffer is Undefined Behavior. This is a design defect, therefore the function is deprecated / removed in newer versions, and just mentioned here for completeness: gets().
Caller passes a callback:
The callback-function gets a context-parameter: qsort_s()
The callback-function gets no context-parameter. Getting the context requires magic: qsort()
Caller passes an allocator: Not found in the C standard library. All allocator-aware C++ containers support that though.
Callee contract specifies the deallocator. Calling the wrong one is Undefined Behavior: fopen()->fclose() strdup()->free()
Callee returns an object which contains the deallocator: COM-Objects
Callee uses an internal shared buffer: asctime()
Be aware that either the returned array must contain a sentinel object or other marker, you have to return the length separately, or you have to return a struct containing a pointer to the data and the length.
Pass-by-reference (pointer to size or such) helps there.
In general, whenever the user has to guess the size or look it up in the manual, he will sometimes get it wrong. If he does not get it wrong, a later revision might invalidate his careful work, so it doesn't matter he was once right. Anyway, this way lies madness (UB).
For the rest, choose the most comfortable and efficient one you can.
Regarding an error code: Remember there's errno.
Usually it's more convenient and semantic to return the array
int* f(..data..)
If ever you need complexe error handling (e.g., returning errors values), you should return the error as an int, and the array by value.
There is no "better" here: you decide which approach fits the needs of the callers better.
Note that both functions are bound to give a user an array that they allocate internally, so deallocating the resultant array becomes a responsibility of the caller. In other words, somewhere inside f() you would have a malloc, and the user who receives the data must call free() on it.
You have another option here - let the caller pass the array into you, and return back a number that says how many items you put back into it:
size_t f(int *buffer, size_t max_length)
This approach lets the caller pass you a buffer in a static or in the automatic memory, thus improving flexibility.
the classic model is (assuming you need to return error code too)
int f(...., int **arr)
even though it doesnt flow so nicely as a function returning the array
Note this is why the lovely go language supports multiple return values.
Its also one of the reasons for exceptions - it gets the error indicators out of the function i/o space
The first one is better if there is no requirement to deal with an already existent pointer in the function.
The second one is used when you already have a defined pointer that points to an already allocated container (for example a list) and inside the function the value of the pointer can be changed.
If you must call f like int* x; f(&x);, you do not have much of a choice. You must use the second syntax, i.e., void f(..data..,int** arr). This is because you are not using return value anyways in your code.
The approach depends on a specific task and perhaps on your personal taste or a coding convention adopted in your project.
In general, I'd like to pass pointers as "output" parameters instead of return'ing an array for a number of reasons.
You likely want to return a number of elements in the array together with the array itself. But if you do this:
int f(const void* data, int** out_array);
Then if you see the signature first time, you can't quite tell what the function returns, the number of elements, or an error code, so I prefer to do this:
void f(const void* data, int** out_array, int* out_array_nelements);
Or even better:
void f(const void* data, int** out_array, size_t* out_array_nelements);
The function signature must be self-explanatory, and the parameter names help to achieve that.
The output array needs to be stored somewhere. You need to allocate some memory for the array. If you return a pointer to the array without passing the same pointer as argument, then you can't allocate memory on the stack. I mean, you cannot do this:
int f (const void *data) {
int array[10];
return array; /* the array is likely deallocated when the function exits */
}
Instead, you have to do static int array[10] (which is not thread-safe) or int *array = malloc(...) which leads to memory leaks.
So I suggest you to pass a pointer to the array which is already allocated before the function call, like this:
void f(const void *data, int* out_array, size_t* out_nelements, size_t max_nelements);
The benefit is you are free to choose where to allocate the array:
On the stack:
int array[10] = { 0 };
size_t max_nelements = sizeof(array)/sizeof(array[0]);
size_t nelements = 0;
f(data, array, &nelements, max_nelements);
Or in the heap:
size_t nelements = 0;
size_t max_nelements = 10;
int *array = malloc(max_nelements * sizeof(int));
f(data, array, &nelements, max_nelements);
See, with this approach you are free to choose how to allocate the memory.
I'm trying to learn on C multithreading, and I've seen a couple of rare things.
I understand that passing parameters to a thread must be done with pointers. I've found an example which I don't understand. I'll copy the relevant lines:
pthread_t tid[MAX_THREADS]
int n_veg
pthread_create(&tid[n],NULL,caracter,(void *)n_veg)
caracter is obviously a predeclared function.
Now, why do we use a void pointer casting instead of a int pointer casting? Is there any relevant difference?
Secondly, why do we use a pointer casting in the first place? Can't we use "&n_veg" like with the first parameter?
Thanks in advance.
Since both your questions are related, I'll answer them together: pthread_create takes a void * parameter, so you can really pass in any pointer you want. In this case though, we aren't actually passing a pointer, but just a simple integer value casted as a pointer. That means you will access it like this in caracter:
int value = (int)n_veg;
As you mentioned, you could very well pass an actual pointer as &n_veg and retrieve the value like this:
int value = *(int *)n_veg;
In fact, in most cases, you will need to pass more data than just an integer, such as a structure, and in that case, you must pass a pointer, as you can't simply cast it to a pointer like an integer.
One thing to keep in mind when you pass a pointer is that n_veg must not go out of scope as long as the thread is running. For example, if you do:
void test() {
int n_veg;
pthread_create(&tid[n],NULL,caracter,&n_veg);
}
then &n_veg will be invalid as soon as test returns, but the thread may still be running and will be holding an invalid address. Because of this, structures passed to threads are normally dynamically allocated, say using malloc, and the thread can free it once it has completed.
pthread_create is defined as follows:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void *), void *restrict arg);
So it expects a void * as its last parameter. If you omit the cast, the compiler would give you a warning.