How to set value of unsigned char array on C - c

I have an unsigned char array of size 64 that i want to change value of at runtime, however all my attemps have failed miserably, what am I doing wrong?
int main() {
unsigned char buffer[64]={0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08,......};
buffer = {0x01,0x04,0xa0,0xb0,0xde,0x00,.....}; //fails
return 0;
}
EDIT: I don't want to fill with zero's the array buffer, I want to place a new value

Another solution would be the use of almighty memcpy() and C99 compound literals:
memcpy(array, (int []){ 0x00, 0x01, 0x02 }, sizeof array);
Believe it or not, this works.

for (int i = 0; i < 64; ++i) buffer[i] = 0x00;
or in C++ (11 or later), you can use std::fill_n or std::generate_n
std::fill_n(buffer, 64, 0x00);
or
for (auto &b : buffer) b = 0x00;

From your comment I see you do not want to access elements of the array. If not, then here is another solution to your problem.
You could declare the buffer on the memory pool. Hence,
unsigned char *buffer = malloc( sizeof( unsigned char ) * 64 );
... and then if you ever wanted to replace all of the elements of the array (as you have attempted to do using the array initialization syntax), it would be done as follows:
memset( buffer, 0x00, sizeof( unsigned char ) * 64 ); // To replace buffer = { 0x00, ..., 0x00 };.
memset( buffer, 0, sizeof( unsigned char ) * 64 ); // To replace buffer = '0...0';.
Legacy:
If you wanted to use an array declared on the stack then you would need to mutate it one element at a time using the square brackets [ ]. It would be done as follows:
for ( int i = 0; i < 64; i++ ) {
buffer[ i ] = val; // where "val" is some value.
}

Use std::memset:
memset(buffer, 0, sizeof(buffer));
There's also bzero, but it's a legacy function, so it shouldn't be used in new development.

You can change the values of the element in two ways :
unsigned char buffer[64]={0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08,......};
buffer[0] = 0;
buffer[1] = 15;
// etc ...
// C++11 for-loop range works fine to :
for ( auto &c : buffer )
c = 0;
Or after that, you can use function like : memset, std::fill_n :
memset( buffer, 0, sizeof(buffer) );
std::fill_n( buffer, 64, 0x00 );

You could use snprintf:
#include <stdio.h>
int main() {
unsigned char buffer[64]={0};
snprintf(buffer, 64, "Hello World!\x0D\x0A");
printf(buffer);
}
Output:
$ ./a.out | hexdump -C
00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0d 0a |Hello World!..|
0000000e

Initialization and assignment are two different operations, despite similarity in the syntax.
int x[4] = { 1, 2, 3, 4}; // initialization
x = { 1, 2, 3, 4}; // assignment
Additionally, raw arrays in C and C++ behave strangely and in particular there's a special rule that says that they are not assignable:
int x[4];
int y[4];
y = x; // error, arrays are not assignable
So even if you create an array temporary object you cannot simply copy that into another array object using the assignment operator.
Instead, if you are set on using raw arrays, you have to set each array element individually, using memcpy, fill, etc.
A better solution is to use C++ and a type other than raw arrays which does allow assignment, such as std::array<unsigned char, 64>:
std::array<unsigned char, 64> buffer = {0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08};
buffer = {}; // zeros out the array
The std::array template just generally behaves consistently like a normal object whereas raw arrays in C and C++ have all these very strange behaviors and special cases in the language specs. You should avoid using raw arrays.
Unfortunately C does not have any alternative to raw arrays.

Since that are some compiler issues, try a simple usage of memcpy().
#include <string.h>
int main() {
unsigned char bufferTo[ 64]={0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08,......};
unsigned char bufferFrom[64]={0x01,0x04,0xa0,0xb0,0xde,0x00,.....};
memcpy(bufferTo, bufferFrom, 64);
return 0;
}

Related

Pass char* to const char* in c

I got a problem. I want to use one CopyString() function to copy const char*s and char*s to a buffer. It shouldn't be a problem but for some reason my compiler doesn't do the thing I expect it to do (I use MikroC for PIC pro).
void CopyString(char * dest, const char * src, uint8 maxLength){
uint8 i;
for(i=0 ; src[i] && ( i < maxLength ) ; i++){
dest[i] = src[i];
};
}
char test[3]={'2', '0', ' '};
CopyString(buf, test, 3);//gives an error (illigal pointer conversion)
CopyString(buf, (const char *)test, 3); //Doesn't pass the pointer to the array... No idea why not... Do you?
void CopyString2(char * dest, char * src, uint8 maxLength){
uint8 i;
for(i=0 ; src[i] && ( i < maxLength ) ; i++){
dest[i] = src[i];
};
}
const char test[3]={'2', '0', ' '};
CopyString2(buf, "20 ", 3);//All ok
CopyString2(buf, test, 3); //gives an error (illigal pointer conversion)
Anyone knows how to do this? Currently I use CopyString2() and CopyString() in one C document which isn't looking nice and it shouldn't be required. Why would pass a char* to a const char* give problems? The only thing const char* does is making sure the data in the char array won't change within the function, right?
Edit:
Here an edit with the 'whole' example code (which should be a Minimal, Complete, and Verifiable example).
With Keil compiler (which I use to program for ARM mcu's) it compiles just fine (like I would expect) but with MikroC PIC compiler (as far as I can find this is how the compiler is called.) it gives the following error:
18 384 Illegal pointer conversion main.c
(line 18, message no. 384)
23 384 Illegal pointer conversion main.c
(line 23, message no. 384)
void CopyString(char * dest, const char * src, unsigned char maxLength){
unsigned char i;
for(i=0 ; src[i] && ( i < maxLength ) ; i++){
dest[i] = src[i];
};
}
void CopyString2(char * dest, char * src, unsigned char maxLength){
unsigned char i;
for(i=0 ; src[i] && ( i < maxLength ) ; i++){
dest[i] = src[i];
};
}
void main(){
char buf[16]={0,};
char test1[3]={'2', '0', ' '};
const char test2[3]={'2', '0', ' '};
CopyString(buf, test1, 3);//gives an error (illigal pointer conversion);
CopyString(buf, (const char *)test1, 3); //Doesn't pass the pointer to the array
CopyString2(buf, "20 ", 3);//All ok
CopyString2(buf, test2, 3); //gives an error (illigal pointer conversion);
}
It's a problem related to how const variables are implemented for PIC controller. In PIC controllers the RAM and Code are located in different types of memory. RAM is SD-RAM, and code is flash memory.(RAM is accessible through register and ram operations, and code is only automatically decoded, or read through a complicated sequence of assembly operations.) Since the RAM is very small, const values are stored as Return Literal instructions in the Code Memory(To bypass the difficulty of reading Flash memory otherwise), which is larger.
So you can't really do the same operations on both types. It's something you need to learn to live with. I suggest you look at the disassembly of this code to see what's really going on.
I've seen this before in other compilers a long time ago - note I've never used this compiler before.
The "array is-a pointer" concept of C causes a lot of problems with newbies. To prevent that, some compiler writers got very pernickety (it's a word! Look it up!) and required you to pass the address of a character to a const char * instead of merely an array.
Can you try CopyString2(buf, &test[0], 3);?
Or even CopyString2(buf, (const char *)&test[0], 3);?

How to create a multiple null-terminated char array?

I have a char array and I want it to have a certain format, for example:
(first 4 bytes) block type
(next 4 bytes) error code
(next 32 bytes)
email address
(next 64 bytes) home address
(next 32 bytes) Full Name
and so forth. About 45 different fields that are padded with 0's to field size. I can use memcpy and advance the pointer each time by the field size but it seems like a tedious task and an ugly code. Maybe a more clever and elegant way to create such a format?
You can do such it using union together with struct:
#define BLOCK_TYPE_SIZE 4
#define ERROR_CODE_SIZE 4
#define EMAIL_ADDRESS_SIZE 32
#define HOME_ADDRESS_SIZE 64
#define FULL_NAME_SIZE 32
struct format_entry
{
char block_type[BLOCK_TYPE_SIZE];
char error_code[ERROR_CODE_SIZE];
char email_address[EMAIL_ADDRESS_SIZE];
char home_address[HOME_ADDRESS_SIZE];
char full_name[FULL_NAME_SIZE];
};
union format_union
{
char full_string[sizeof(struct format_entry)];
struct format_entry entry;
};
And then you can fill it in like these:
union format_union f;
memset (f.full_string, 0, sizeof f.full_string);
strcpy (f.entry.block_type, "TYPE");
strcpy (f.entry.error_code, "CODE");
strcpy (f.entry.email_address, "EM#AI.L");
strcpy (f.entry.home_address, "ADDR");
strcpy (f.entry.full_name, "NA ME");
strncpy(), despite its name, is not a "string" function
char data[136/* maybe add 1 for extra '\0' */] = {0}; // fill array with zeroes
strncpy(data, "block type", 4);
strncpy(data + 4, "error code", 4);
strncpy(data + 8, "email address", 32);
strncpy(data + 40, "home address ...", 64);
strncpy(data + 104, "Full Name even if it is very very long", 32);
To add to Nick's response, in C, but not C++, you can skip the union and directly zero the structure:
struct format_entry
{
char block_type[BLOCK_TYPE_SIZE];
char error_code[ERROR_CODE_SIZE];
char email_address[EMAIL_ADDRESS_SIZE];
char home_address[HOME_ADDRESS_SIZE];
char full_name[FULL_NAME_SIZE];
};
struct format_entry data;
memset( &data, 0, sizeof data ); /* zero-fill structure */
If you need to update just some of the fields later on you might also consider making your own fill routine that assures zero fill.
char *strncpy0( char *target, const char *source, size_t s )
{
memset( target, 0, s );
strncpy( target, source, s );
return target;
}
While the above code is safer for early users of C, to be more efficient you could calculate the number of bytes at the end of target that strncpy() will not touch, then just fill those bytes.
That's truly a tedious task. But it seems there is no better way.
Maybe you could conceal them into functions and never consider the ugly code inside.

Find the size of a string pointed by a pointer

#include <stdio.h>
int main ()
{
char *ptr = "stackoverflow"
}
Is there any way to find the length of stackoverflow pointed by ptr, as sizeof ptr always gives 4
Use strlen to find the length of (number of characters in) a string
const char *ptr = "stackoverflow";
size_t length = strlen(ptr);
Another minor point, note that ptr is a string literal (a pointer to const memory which cannot be modified). Its better practice to declare it as const to show this.
sizeof() returns the size required by the type. Since the type you pass to sizeof in this case is a pointer, it will return size of the pointer.
If you need the size of the data pointed by a pointer you will have to remember it by storing it explicitly.
sizeof() works at compile time. so, sizeof(ptr) will return 4 or 8 bytes typically. Instead use strlen.
The strlen() function provided by string.h gives you how many "real characters" the string pointed by the argument contains. However, this length does not include the terminating null character '\0'; you have to consider it if you need the length to allocate memory.
That 4 bytes is the size of a pointer to char on your platform.
#include<stdio.h>
main()
{
int mystrlen(char *);
char str[100];
char *p;
p=str;
printf("Enter the string..?\n");
scanf("%s",p);
int x=mystrlen(p);
printf("Length of string is=%d\n",x);
}
int mystrlen(char *p)
{
int c=0;
while(*p!='\0')
{
c++;
*p++;
}
return(c);
}
simple code to understand
You are looking for the strlen() function.
You can try using:
char *ptr = "stackoverflow"
size_t len = strlen(ptr);
if ptr length is an argument of a function it's reasonable to use pointers as a strings. we can get string length by following code:
char *ptr = "stackoverflow";
length=strlen((const char *)ptr);
And for more explanation, if string is an input string by user with variable length, we can use following code:
unsigned char *ptr;
ptr=(unsigned char *)calloc(50, sizeof(unsigned char));
scanf("%s",ptr );
length=strlen((const char *)ptr);
Purely using pointers you can use pointer arithmetic:
int strLen(char *s)
{
int *p = s;
while(*p !=’\0’)
{
p++; /* increase the address until the end */
}
Return p – s; /* Subtract the two addresses, end - start */
}
Even though this is a generic C question, it gets pretty high hits when looking this question up for C++. Not only was I in C/C++ territory, I also had to be mindful of Microsoft's Security Development Lifecycle (SDL) Banned Function Calls for a specific project which made strlen a no-go due to,
For critical applications, such as those accepting anonymous Internet connections, strlen must also be replaced...
Anyway, this answer is basically just a twist on the answers from the others but with approved Microsoft C++ alternative function calls and considerations for wide-character handling in respect to C99's updated limit of 65,535 bytes.
#include <iostream>
#include <Windows.h>
int wmain()
{
// 1 byte per char, 65535 byte limit per C99 updated standard
// https://stackoverflow.com/a/5351964/3543437
const size_t ASCII_ARRAY_SAFE_SIZE_LIMIT = 65535;
// Theoretical UTF-8 upper byte limit of 6; can typically use 16383 for 4 bytes per char instead:
// https://stijndewitt.com/2014/08/09/max-bytes-in-a-utf-8-char/
const size_t UNICODE_ARRAY_SAFE_SIZE_LIMIT = 10922;
char ascii_array[] = "ACSCII stuff like ABCD1234.";
wchar_t unicode_array[] = L"Unicode stuff like → ∞ ∑ Σὲ γνωρίζω τὴν ደሀ ᚦᚫᛏ.";
char * ascii_array_ptr = &ascii_array[0];
wchar_t * unicode_array_ptr = &unicode_array[0];
std::cout << "The string length of the char array is: " << strnlen_s(ascii_array_ptr, ASCII_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
std::wcout << L"The string length of the wchar_t array is: " << wcsnlen_s(unicode_array_ptr, UNICODE_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
return 0;
}
Output:
The string length of the char array is: 27
The string length of the wchar_t array is: 47
strlen() gives you the exact length of the string [excluding '\0']
sizeof() gives you the size of the data type used.
// stackoverflow = 13 Characters
const char* ptr = "stackoverflow";
strlen(ptr); // 13 bytes - exact size (NOT includes '\0')
sizeof(ptr); // 4 bytes - Size of integer pointer used by the platform
sizeof(*ptr); // 1 byte - Size of char data type
strlen("stackoverflow"); // 13 bytes - exact size
sizeof("stackoverflow"); // 14 bytes - includes '\0'
#include<stdio.h>
int main() {
char *pt = "String of pointer";
int i = 0;
while (*pt != '\0') {
i++;
pt++;
}
printf("Length of String : %d", i);
return 0;
}
We can also use strlen() function or sizeof() operator which is builtin in C.
We can also take help of pointer arithmetic as above example.

C Program: setting up array of strings when length is not known at compile time

I'm trying adapt the example code shown in the "Array Interface Example" section here,
http://orclib.sourceforge.net/doc/html/group_g_bind.html
where they place an array of strings, tab_str, into OCI_BindArrayOfStrings using:
char tab_str[1000][21];
...
OCI_BindArrayOfStrings(st, ":s", (char*) tab_str, 20, 0);
The problem is, the above example knows the array length at compile time, whereas I have to download this length from a database when the program is run. So I'd like to create an array of strings, called my_tab_str and place it in the following line of code:
OCI_BindArrayOfStrings(st, ":s", (char*) my_tab_str, 20, 0);
My question is how to set up my_tab_str? Here's my code (compiled using gcc -std=C89):
int i, arraysize;
char person_name[20] = "";
char * my_tab_str;
...
strncpy(person_name, "John Smith", 19);
arraysize = <this value is downloaded from database>;
...
my_tab_str = malloc( arraysize * sizeof(char) * (strlen(person_name)+1) );
for(i=0;i<arraysize;i++) {
strncpy( my_tab_str[i], person_name, strlen(person_name) );
}
The goal is to place "John Smith" (e.g 10 bytes) plus a null termination character (which I think is automatically added by the compiler) into each element of the array of strings my_tab_str.
I'm getting the compile warning: warning: passing argument 1 of 'strncpy' makes pointer from integer without a cast
/usr/include/string.h:131: note: expected 'char * __restrict__' but argument is of type 'char'
Note that the function OCI_BindArrayOfStrings is described here:
http://orclib.sourceforge.net/doc/html/group_g_bind.html#ga502cd4785691b17955f5d99276e48884
and expects an array of string as an argument. See the example code at the first link above for an example implementation.
For array of strings, you need to declare my_tab_str as char** and then allocate memory for it.
my_tab_str = malloc(ROWS * sizeof(char*)); //ROW is no of strings
Then,
for(int i=0;i<ROWS;i++)
my_tab_str[i] = malloc(COLUMNS * sizeof(char)); //COLUMN is the size for each string.
It's not entirely clear from your post what that function expects as an argument. I'm going to assume it's a char **.
In that case, you need to do something like this:
// Allocate an array of pointers
char **my_tab_str = calloc(arraysize, sizeof(*my_tab_str));
// Allocate room for each string in turn
for (int i = 0; i < arraysize; i++) {
// person_name comes from somewhere
const int len = strlen(person_name);
my_tab_str[i] = calloc(len+1, sizeof(*my_tab_str[i]));
strncpy(my_tab_str[i], person_name, len);
}
UPDATE
Ok, so it looks like that function takes a char * which points to a contiguous 1D array of all the strings concatenated, along with the number of strings, and the length of each string. In which case, you'll need to do something like this:
const int len = strlen(person_name);
// Big 1D array
char *my_tab_str = calloc(arraysize*(len+1), sizeof(*my_tab_str));
// Put each string into the 1D array, at regular intervals
for (int i = 0; i < arraysize; i++) {
strncpy(&my_tab_str[i*(len+1)], person_name, len);
}
This is just a guess though, because that function really isn't well-documented.
Obviously, you will also need some cleanup code at some point that carefully frees everything.
And if you want to be really careful, you should add error-handling code that checks the result of each calloc for NULL, but that would clutter the example, so I've omitted it.
It appears that by string, they mean unsigned char *. You want an array of these, and they are using the (somewhat unusual) convention that an array of strings is a contiguous block of memory, so you declare it as:
unsigned char *my_tab_str;
size_t namesize = 20; // Better still, use a #define so 20 isn't a mysterious magic number
And you initialize it as follows:
my_tab_str = malloc( arraysize * sizeof( unsigned char *) * (namesize+1) ); // +1 for the null
for( int i = 0; i < arraysize; ++i )
{
strncpy( &my_tab_str[i*(namesize+1)], person_name, namesize );
}
The first line (malloc) allocates enough memory for arraysize strings, each with room for namesize characters, plus a null. The strncpy copies into each of them a maximum namesize bytes, followed by a null ('\0'). Each time we pass a pointer to the next location, which is namesize+1 bytes beyond the previous one.

char arrays length in C

In C, you have to declare the length of an array:
int myArray[100];
But when you're dealing with chars and strings, the length can be left blank:
char myString[] = "Hello, World!";
Does the compiler generate the length for you by looking at the string?
This is not unique to char. You could do this, for instance:
int myNumbers[] = { 5, 10, 15, 20, 42 };
This is equivalent to writing:
int myNumbers[5] = { 5, 10, 15, 20, 42 };
Initialising a char array from a string literal is a special case.
Yes, it's the length including the terminating '\0'.
Does the compiler generate the length for you by looking at the string?
Yes, that's exactly why it works. The compiler sees the constant value, and can fill in the length so you don't have to do it.
Yes, the compiler knows the length of the string and allocates the appropriate space.
It's the same deal if you did something like...
int x[] = {1,2,3};
The size of the string literal (not length as in strlen) is used to size the array being initialized.
You can initialize a char array with a string literal which has embedded null bytes. The resulting array will have size for all the bytes after the first (or second, ...) null.
char array[] = "foo\0bar\0baz\0quux";
/* sizeof array is 17
** array[3] is 0
** printf("%s\n", array + 4); prints bar
** array[11] is 0
** printf("%s\n", array + 12); prints quux
** array[16] == 0
*/

Resources