C: byte-copy unsigned char value - c

void callback(const unsigned char* data, int len) {
unsigned char copydatahere;
}
data is a pointer-to-const situation, that is allocated in library outside. len is a size of data, guessing it to be sizeof(unsigned char)*N.
How I allocate copydatahere to size of len and copy the whole memory behind data including null bytes, string termination chars and anything other that has byte representation? What would be the difference between bcopy and memcpy in this situation?
Addition:
memcpy(pointer+offset, sourcedata, size);that's how you can do 'memcpy append' guys. Thank you all!

Use memcpy. bcopy is only supported on some platforms, and is deprecated in newer standards.
void callback(const unsigned char* data, int len) {
unsigned char* copydatahere = malloc(len);
if (!copydatahere) {
exit(1);
}
memcpy(copydatahere, data, len);
/* ... */
free(copydatahere);
}

Allocate with malloc(3), release with free(3). bcopy(3), while deprecated (so prefer memmove(3)), handles overlapping memory regions, memcpy(3) doesn't.

#include <assert.h>
#include <stdlib.h>
void callback(const unsigned char *data, int len) {
assert(len >= 0);
unsigned char *copy = malloc(len);
if (copy == NULL) { abort(); }
memcpy(copy, data, len);
/* TODO: Store the length somewhere, since otherwise the pointer is useless. */
/* TODO: pass the pointer "copy" somewhere, so it is used. */
}
Usually the second argument to such a callback function is some unsigned type like unsigned int or size_t. Therefore I added the assert, just to be sure that there won't be any undefined behavior.
memcpy is well-defined in the C standard, while bcopy is the old version and is not guaranteed to exist or even work as you expect. (Though usually if it exists it will do what you expect.)

Just create an array
void callback(const unsigned char* data, int len) {
unsigned char copydatahere[len];
memcpy(copydatahere, data, len);
}
If len can be arbitrarily large (say, like 4 million), it's better to use malloc though, because it can tell you whether allocation succeeded or not (although some operation systems in certain configurations will lie to you, telling you enough memory is available, only to then later crash when you try to access it). If the above array's allocation fails, behavior is undefined.
Not all compiles support arrays with a variable size, though.

Related

Is this method of copying a string faster than copying each char individually?

Is this method of copying a string faster than copying each char individually? The idea of this code is that it could (but I am not sure if it is so) be faster to copy 8 bytes at once instead of a single byte. It is very un-safe but it seems to work somehow. Or it's just a bad idea?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void* copy_string(char s[])
{
int len=strlen(s);
int i=0;
double *p=(double*)s;
double *copy=(double*)malloc(len+1);
while(i-len>8)
{
*copy=*(p++);
copy++;
i+=8;
}
char *p2=(char*)p;
char *c=(char*)copy;
while(i<len)
{
*c=*(p2++);
c++;
i++;
}
*c='\0';
return copy;
}
int main()
{
char s[]="GOODBYE SAFE WORLD!";
char *c=copy_string(s);
printf("%s",c);
return 0;
}
Tricks like that may be faster under some circumstances on some architectures. Trust your provider of your C library to know about these tricks if they apply.
In your case, your code is simply wrong. Assuming that the condition of the first while loop is fixed, the rules for pointer conversions are violated:
A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned for the referenced type, the behavior is undefined.
On many architectures this will simply result in a "bus error".
To see how these kind of tricks work, check out the sources of your favorite C library and look for their implementation of memcpy and memmove.

How do I write a C function that returns a variable-length string?

I need to be able to check in a kernel module whether or not a file descriptor, dentry, or inode falls under a certain path. To do this, I am going to have to write a function that when given a dentry or a file descriptor (not sure which, yet), will return said object's full path name.
What is the way to write a function that returns variable-length strings?
You can try like this:
char *myFunction(void)
{
char *word;
word = malloc (sizeof (some_random_length));
//add some random characters
return word;
}
You can also refer related thread: best practice for returning a variable length string in c
The typical way to do this in C, is not to return anything at all:
void func (char* buf, size_t buf_size, size_t* length);
Where buf is a pointer to the buffer which will hold the string, allocated by the caller. buf_size is the size of that buffer. And length is how much of that buffer that the function used.
You could return a pointer to buf as done by for example strcpy. But this doesn't make much sense, since the same pointer already exists in one of the parameters. It adds nothing but confusion.
(Don't use strcpy, strcat etc functions as some role model for how to write functions. Many C standard library functions have obscure prototypes, because they are so terribly old, from a time when good programming practice wasn't invented, or at least not known by Dennis Ritchie.)
There are two common approaches:
One is to have a fixed size buffer to store the result:
int makeFullPath(char *buffer,size_t max_size,...)
{
int actual_size = snprintf(buffer,max_size,...);
return actual_size;
}
Examples of standard functions which use this approach are strncpy() and snprintf(). This approach has the advantage that no dynamic memory allocation is needed, which will give better performance for time-critical functions. The downside is that it puts more responsibility on the caller to be able to determine the largest possible result size in advance or be ready to reallocate if a larger size is necessary.
The second common approach is to calculate how big of a buffer to use and allocate that many bytes internally:
// Caller eventually needs to free() the result.
char* makeFullPath(...)
{
size_t max_size = calculateFullPathSize(...);
char *buffer = malloc(max_size);
if (!buffer) return NULL;
int actual_size = snprintf(buffer,max_size,...);
assert(actual_size<max_size);
return buffer;
}
An example of a standard function that uses this approach is strdup(). The advantage is that the caller no longer needs to worry about the size, but they now need to make sure that they free the result. For a kernel module, you would use kmalloc() and kfree() instead of malloc() and free().
A less common approach is to have a static buffer:
const char *makeFullPath(char *buffer,size_t max_size,...)
{
static char buffer[MAX_PATH];
int actual_size = snprintf(buffer,MAX_PATH,...);
return buffer;
}
This avoids the caller having to worry about the size or freeing the result, and it is also efficient, but it has the downside that the caller now has to make sure that they don't call the function a second time while the result of the first call is still being used.
char *result1 = makeFullPath(...);
char *result2 = makeFullPath(...);
printf("%s",result1);
printf("%s",result2); /* oops! */
Here, the caller probably meant to print two separate strings, but they'll actually just get the second string twice. This is also problematic in multi-threaded code, and probably unusable for kernel code.
For example:
char * fn( int file_id )
{
static char res[MAX_PATH];
// fill res[]
return res;
}
/*
let do it the BSTR way (BasicString of VB)
*/
char * CopyString(char *str){
unsigned short len;
char *buff;
len=lstrlen(str);
buff=malloc(sizeof(short)+len+1);
if(buff){
((short*)buff)[0]=len+1;
buff=&((short*)buff)[1];
strcpy(buff,str);
}
return buff;
}
#define len_of_string(s) ((short*)s)[-1])
#define free_string(s) free(&((short*)s)[-1]))
int main(){
char *buff=CopyString("full_path_name");
if(buff){
printf("len of string= %d\n",len_of_string(buff));
free_string(buff);
}else{
printf("Error: malloc failed\n");
}
return 0;
}
/*
now you can imagine how to reallocate the string to a new size
*/

Passing a char buffer to function

I have some problems with a pointer. My idea was to pass a buffer to a function in order to store the return data in this buffer. But, I do not know if it will work.
void main()
{
char *buf = malloc(sizeof(char) *buf);
memset(buf, 0x00, BUF_SIZE);
sendCommand(buf);
}
sendCommand(char *buf)
{
write(fd, "some commands", strlen("some commands"));
readResponse(buf);
}
readResponse(char *buf)
{
read(fd, buf, nbytes);
}
I know there is no error handling up to now. And some variables are not well defined. It just depends on the passing buffer. Will I see the data that I get in readResponse() in my main function?
As in readResponse() as you read nbytes into buffer pointed by buf ,so you will get that data in main .
Some improvements to be done -
1. void main() -> int main(void) or int main(int argc, char *argv[])
2. char *buf = malloc(sizeof(char) *buf); -> char *buf = malloc(BUF_SIZE); // sizeof(char)=1 or maybe something you desire (not sure though what you want ??)
Note - remember to free allocated memory.
You have a remarkable number of significant problems in the code you presented, considering how short it is. Other answers have addressed those, though, and your question is not actually about any of them:
Will I see the data I get in readResponse() in my main function?
Yes, provided that argument buf is a pointer to an array large enough to accommodate nbytes bytes, and that the read() call in fact successfully reads any bytes, those bytes will afterward be visible in main() via the pointer it passed to readResponse(). More generally, if you pass a pointer as a function argument, the called function may manipulate the pointed-to object, including by modifying those parts of it that are not const. That's how the read() function itself is able to store the bytes it reads into your buffer, after all.
This won't do what you think it does:
char *buf = malloc(sizeof(char) *buf);
Did you mean to multiply with BUF_SIZE?

Is there a way create an array with a variable length in c?

Is there any way (other than malloc) for creating an array with a size that the user inputs?
It all depends on the compiler.
Variable-length automatic arrays are allowed in ISO C99, and as an
extension GCC accepts them in C90 mode and in C++. These arrays
are declared like any other automatic arrays, but with a length that
is not a constant expression. The storage is allocated at the point of
declaration and deallocated when the brace-level is exited. For
example:
FILE *
concat_fopen (char *s1, char *s2, char *mode)
{
char str[strlen (s1) + strlen (s2) + 1];
strcpy (str, s1);
strcat (str, s2);
return fopen (str, mode);
}
See this for more information.
One way is to use a VLA (C99 defines what are called 'Variable Length Arrays').
Here is an example:
#include <stdio.h>
int use_a_vla (int n)
{
int vla[n]; /* Array length is derived from function argument. */
vla[0] = 10;
vla[n-1] = 10;
return 0;
}
int main (void)
{
int i;
scanf ("%d", &i); /* User input. */
use_a_vla (i);
}
If you don't have VLAs or alloca(), here is an extremely kludgy, but portable, stack-based technique:
int foo(int size)
{
if (size <= 64*1024)
{
unsigned char arr[64*1024];
return bar(arr, size);
}
else if (size <= 1*1024*1024)
{
unsigned char arr[1*1024*1024];
return bar(arr, size);
}
else if (size <= 64*1024*1024)
{
unsigned char arr[64*1024*1024];
return bar(arr, size);
}
else
return -1; // Assume it's too big
}
int bar(unsigned char arr[], int size)
{
...your code goes here...
}
int maincode(int size)
{
// Invoke bar() indirectly, allocating an array
// on the stack of at least 'size' bytes
return foo(size);
}
I don't particularly recommend this technique, but it will give you differently-sized blocks of memory allocated on the stack instead of the heap.
Well, this is pedantic, but you can write your own heap management code and call your memory allocation function something other than malloc(). I hope this answer is amusing rather than annoying.
I assume you're trying to avoid malloc because you don't know about realloc.
Essentially, you should be trying to do roughly what the C++ vector does. Once your array grows to a certain size, realloc it to twice its size.
realloc will grow your memory block if possible, and if not possible it will malloc a new one and copy the contents across.

Problem with pointer copy in C

I radically re-edited the question to explain better my application, as the xample I made up wasn't correct in many ways as you pointed out:
I have one pointer to char and I want to copy it to another pointer and then add a NULL character at the end (in my real application, the first string is a const, so I cannot jsut modify it, that's why I need to copy it).
I have this function, "MLSLSerialWriteBurst" which I have to fill with some code adapt to my microcontroller.
tMLError MLSLSerialWriteBurst( unsigned char slaveAddr,
unsigned char registerAddr,
unsigned short length,
const unsigned char *data )
{
unsigned char *tmp_data;
tmp_data = data;
*(tmp_data+length) = NULL;
// this function takes a tmp_data which is a char* terminated with a NULL character ('\0')
if(EEPageWrite2(slaveAddr,registerAddr,tmp_data)==0)
return ML_SUCCESS;
else
return ML_ERROR;
}
I see there's a problem here: tha fact that I do not initialize tmp_data, but I cannot know it's length.
For starters, you are missing a bunch of declarations in your code. For example, what is lungh? Also, I'm assuming you initialized your two pointers so they point to memory you can use. However, maybe that's not a safe assumption.
Beyond that, you failed to terminate your from string. So getting the length of the string will not work.
There seems to be numerous errors here. It's hard to know where to start. Is this really what your actual code looks like? I don't think it would even compile.
Finally, there seems to be a bit of confusion in your terminology. Copying a pointer is different from copying the memory being pointed to. A pointer is a memory address. If you simply copy the pointer, then both pointers will refer to the same address.
I would create a copy of a string using code similar to this:
char *from_string = "ciao";
char *to_string;
int len;
len = strlen(from_string);
to_string = (char *)malloc(len + 1);
if (to_string != NULL)
strcpy(to_string, from_string);
Be fully aware that you do not want to copy a pointer. You want to copy the memory that is pointed to by the pointer. It does sound like you should learn more about pointers and the memory environment of your system before proceeding too much farther.
When you say tmp_data = data, you are pointing tmp_data to the same memory pointed to by data. Instead, you need to allocate a new block of memory and copy the memory from data into it.
The standard way to do this is with malloc. If you do not have malloc, your libraries may have some other way of acquiring a pointer to usable memory.
unsigned char * tmp_data = malloc(length + 1);
if(tmp_data != 0) {
memcpy(tmp_data, data, length);
tmp_data[length] = 0;
// ...
free(tmp_data);
}
You could also use a fixed-size array on the stack:
unsigned char tmp_data[256];
if(length >= sizeof(tmp_data)) length = sizeof(tmp_data) - 1;
memcpy(tmp_data, data, length); // or equivalent routine
tmp_data[length] = 0;
C99 introduced variable-length arrays, which may be what you seek here, if your compiler supports them:
unsigned char tmp_data[length];
memcpy(tmp_data, data, length); // or equivalent routine
tmp_data[length] = 0;

Resources