fill character array by blocks - c

question of curiosity
suppose I have:
int main(void)
{
char str[32];
for (i = 0; i < 32; i++)
str[i] = 0;
}
but I want to do it 4x faster
int main(void)
{
char str[32];
for (i = 0; i < 32 / 4; i += 4)
str[i] = (int)0;
}
I expect that the whole array will be filled with zeros.
but array is not filled by zeroes
my questions: why array not filled by zeroes? how to fill array per int blocks? my question is Research for c feature, how to tell the compiler - write blocks of 4 bytes, ie integer registers, it will reduce the number of memory accesses by 4 times, on x64 processors reduce 8 times
thanks for all, follows work well:
int main(int argc, char *argv[])
{
char str[32];
int i;
for (i = 0; i < 32; i++)
str[i] = 12;
for (i = 0; i < 32 / sizeof(int); i++)
((int *) str)[i] = 0;
printf("%d\n", i);
for (i = 0; i < 32; i++)
printf("%d\n", str[i]);
return 0;
}

The correct and fastest way is to initialize the array to zero
char str[32] = { 0 } ;
If you want to set the array to zero afterwards, then use memset and enable compiler optimization and intrinsic functions, and the compiler will figure out the fastest way to zero the array.
memset( str , 0 , sizeof( str ) ) ;

As pointed out by #user2501, initializing to {0} or using memset is the fastest and correct way.
If you are tempted to use something like ((int *)str)[i] = 0, do not, this can result in unaligned access.
As an alternative to memset, in C99 (and assuming that int is 4 bytes) you can use the type punning feature of unions:
#include <stdio.h>
typedef union {
char as_string[32];
int as_int[8];
} foo;
int main(void)
{
foo x;
int i;
for (i = 0; i < 8; i++)
x.as_int[i] = 0;
for (i = 0; i < 32; i++)
printf("%d", x.as_string[i]);
printf("\n");
return 0;
}
Output:
00000000000000000000000000000000

Seems that you are forced to use pointers and casts, this version uses the heap in order to allocate str on an address properly aligned for int:
#include <stdio.h>
#include <stdlib.h> /* malloc, free */
#include <stdint.h> /* intptr_t (pointer arithmetic using modulo division) */
#define MAX 32
int main(void)
{
size_t i, align;
char *ptr, *str;
align = __alignof__(int);
ptr = malloc(MAX + align); /* MAX + max align distance */
str = ptr + align - (intptr_t)ptr % align; /* now str is properly aligned */
for (i = 0; i < MAX / sizeof(int); i++)
((int *)str)[i] = 0;
for (i = 0; i < MAX; i++)
printf("%d\n", str[i]);
free(ptr);
return 0;
}
Note that __alignof__ is a gcc extension, change to __alignof if you are under Visual Studio or _Alignof if you are comfortable with C11.

You have to cast the pointer as the int, not the value:
int main(void)
{
char str[32];
for (i = 0; i < 32/sizeof(int); i++)
((int *) str)[i] = 0xAABBCCDD; //Be careful of Endianness
}
Alternatively:
int i;
union block_fill
{
char arr[24];
int iarr[6];
};
union block_fill block_arr;
for(i=0; i<6; i++)
block_arr.iarr[i] = 0x11223344;
for(i=0; i<24; i++)
printf("%x", block_arr.arr[i]);

Related

Find the difference between elements in an array and store the results in a new array

This is my current code:
#include <stdio.h>
int index_x[] = {0,0,1,0,1,0,0,0,1,0,0,1,0}; // any number of elements
int len = sizeof index_x / sizeof*index_x;
int main(void) {
int arr[len];
int j = 0;
for (int i = 0; i < len; i++)
if (index_x[i])
arr[j++] = i; // save and advance j only if value is "1"
for (int i = 0; i < j; i++) // only print below j !
printf("%d\n", arr[i]);
}
Output:
2
4
8
11
From this output, I would like to generate another array that is the difference between these elements. In this case the new array would be {2,4,3}. (2-4=2, 8-4=4, 11-8=3).
I am currently struggling with two things:
Saving the array generated from the current code arr[i] as a another array so I can manipulate it for future uses.
Generating the "differences array". The tricky part is that the number of elements will not be constant so I cannot specify an array size.
It may be helpful to break things out into functions.
int indexes_of_non_zero(int *source, size_t len, int **dest) {
*dest = malloc(sizeof(int) * len);
int count = 0;
for (int i = 0; i < len; i++) {
if (source[i] != 0) {
(*dest)[count++] = i;
}
}
*dest = realloc(*dest, sizeof(int) * count);
return count;
}
So we have a function indexes_of_non_zero that takes a source array of ints with size specified by argument len, and then a pointer to an array of ints that will be the destination for our output.
We can naively allocate the same amount of memory to the destination, then loop over the source array and store the indexes of non-zero elements. When we're done, we use count to know the size of destination array. We use realloc to shrink the array to just the needed size. And the key is we return the count so our main function knows how big the destination array is.
We can now create a diffs function to do basically the same thing for the differences.
int diffs(int *source, size_t len, int **dest) {
*dest = malloc(sizeof(int) * (len - 1));
for (int i = 0; i < (len - 1); i++) {
(*dest)[i] = abs(source[i] - source[i + 1]);
}
return len - 1;
}
Putting it all together (not copying and pasting the function implementations for terseness) with a main function, and remembering to free the memory we've used, we get:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int indexes_of_non_zero(int *source, size_t len, int **dest);
int diffs(int *source, size_t len, int **dest);
int main(void) {
int data[] = {0,0,1,0,1,0,0,0,1,0,0,1,0};
size_t len = sizeof(data) / sizeof(*data);
int *nz = NULL;
int *d = NULL;
int nzc = indexes_of_non_zero(data, len, &nz);
int dlen = diffs(nz, nzc, &d);
for (int i = 0; i < nzc; i++) {
printf("%d\n", nz[i]);
}
for (int i = 0; i < dlen; i++) {
printf("%d\n", d[i]);
}
free(nz);
free(d);
}
And compiling and running it, the output is:
2
4
8
11
2
4
3
I changed it to get the differences as direct as possible; the inner loop is very simple.
The size question, first part: I (still) tried to avoid size_t for the input but added some sanity check for the size. Just to show there is a limit.
part two: a first loop to get the sum of true values in advance. Also the booldata array consists of chars and is not called index_x. Index is i.
part three: the diffs VLA gets its exact size, which can be 0 even for huge inputs. Some test could be added here after counting, to rule out a (big) input full of "1".
I added the copying, with message and printout.
#include <stdio.h>
#include <string.h>
char booldata[] = { 0,0,1,0,1,0,0,0,1,0,0,1,0 };
char sz_overf = sizeof booldata > 0xffffL * 0xffff; // too-big-flag for exiting...
int len = sizeof booldata / sizeof * booldata; // ...to keep len below size_t
int sum_of_trues (char *booldata, int len) {
int sum = 0;
for (int i = 0; i < len; i++)
if (booldata[i])
sum++;
return sum;
}
void print_intarr(int *inta, int len) {
for (int i = 0; i < len; i++)
printf("%d\n", inta[i]);
}
int main(void)
{
if (sz_overf) return 100; // len might be overflowed
int unsigned // signed provokes VLA warning: 9 gazillions seems ok, but not 18
dsum = sum_of_trues(booldata, len) - 1; // Invest a counting loop
int diffs[dsum], // VLA
di = 0; // diffs' index
int sti = -1; // Stored last index containing true
for (int i = 0; i < len; i++)
if (booldata[i]) { // true?
if (sti >= 0) { // and is there a left neighbour?
int diff = i - sti; // how far away?
printf("%d\n", diff); // 1. on-the-fly result
diffs[di++] = diff; // 2. for keeps
}
sti = i; // remember last "true"
}
printf("Copying %zu bytes from Diff.-Array\n", sizeof diffs);
int diffscopy[sizeof diffs];
memcpy(diffscopy, diffs, sizeof diffs);
print_intarr(diffscopy, dsum); // dsum or sizeof diffs
return 0;
}
output:
2
4
3
Copying 12 bytes from Diff.-Array
2
4
3
The inner loop could look like this w/o multi-option:
if (booldata[i]) {
if (sti >= 0) // and is there a left neighbour?
diffs[di++] = i - st; // 2. for keeps
sti = i;
}
Two arrays and three variables. The rest is needed to make this work.
BUGS: all-false input segfaults. It takes one "true" to get zero diffs...

Split int into char array in C

I have an int, and I need to split it to a char array, so 2 chars in each array position. After that, I need to do the opposite process. This is the best I could come up with, but I still couldn't make it work. Any suggestions?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int length = 10968;
int bytesNeeded = sizeof(length) / 2;
char *controlPacket = (char*)malloc(sizeof(char*)*bytesNeeded);
for (int i = 0; i < bytesNeeded; i++)
{
controlPacket[i] = (length >> (8* i));
}
int newSize = 0;
for (int i = 0; i < bytesNeeded; i++)
{
newSize += (controlPacket[i] << (8 * i));
}
printf("Newsize is: %d\n", newSize);
}
Change the variables that you're performing bitwise operations on to unsigned, and also mask the result of shifting before assigning to the array. Otherwise, you get overflow, which causes incorrect results (maybe undefined behavior, I'm not sure).
You also shouldn't divide sizeof(length) by 2. It will work for values that only use the low order half of the number, but not for larger values; e.g. if you use length = 1096800; the result will be 48824.
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned int length = 10968;
int bytesNeeded = sizeof(length);
unsigned char *controlPacket = malloc(sizeof(unsigned char)*bytesNeeded);
for (int i = 0; i < bytesNeeded; i++)
{
controlPacket[i] = (length >> (8* i) & 0xff);
}
unsigned int newSize = 0;
for (int i = 0; i < bytesNeeded; i++)
{
newSize += (controlPacket[i] << (8 * i));
}
printf("Newsize is: %d\n", newSize);
free(controlPacket);
}

How to return an array of char pointers? What is wrong in my code?

I have seen similar posts related to my question but I could not find any answer to understand the bug in this code.
So, I have a function whose return type can't be changed (for case 1). For case 2, I would like to know how to return char *a[];
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **myfunc(int n) {
char **a = malloc(n * sizeof(char *));
int i, j = 1;
for (i = 0; i < n; i++)
a[i] = malloc(9 * sizeof(char));
for (i = 0; i < n; i++) {
snprintf(a[i], 5, "%d", i);
return a;
}
int main() {
int num = 10, i;
char **ar = myfunc(num);
for (i = 0; i < num; i++)
printf("%s\n", ar[i]);
return 0;
}
1) In the myfunc(), how should I return a correctly? My compiler is throwing me a warning that return from incompatible pointer type.
2) In case, if I change my above myfunc() as follows, how should I return the modified buffer?
char ???myfunc(int n) {
char *a[n];
for (i = 0; i < n; i++)
a[i] = malloc(10 * sizeof(char));
return ?
}
3) In both cases, how should I handle the return inside the main() function?
Case 2:
char *myfunc(int n) {
static char *a[n];
int i;
for (i = 0; i < n; i++)
a[i] = malloc(9 * sizeof(char));
for (i = 0; i < n; i++)
snprintf(a[i], 5, "%d", i);
return a;
}
int main() {
int num = 10, i;
char *ar = myfunc(num);
for (i = 0; i < num; i++)
printf("%s\n", ar[i]);
return 0;
}
Your code was mis-indented, which makes it hard to read and hides silly mistakes such as the extra brace after the second for.
Once corrected for this mistake, the code compiles and runs fine:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **myfunc(int n) {
char **a = malloc(n * sizeof(char *));
int i;
for (i = 0; i < n; i++)
a[i] = malloc(9 * sizeof(char));
for (i = 0; i < n; i++)
snprintf(a[i], 9, "%d", i);
return a;
}
int main() {
int num = 10, i;
char **ar = myfunc(num);
for (i = 0; i < num; i++)
printf("%s\n", ar[i]);
return 0;
}
If you change myfunc() to define a as char *a[n];, you have a major problem when returning a from myfunc() as the array is defined only inside the scope of myfunc(). Returning its address, which is simply return a; will cause undefined behavior in main() because the space it points to might have been reused for other stuff, such as printf() local variables.
The third option where you define a as static char *a[n]; does not compile because the size of static objects must be known at compile time. Using local static objects is not advisable as it makes the program harder to understand and non-reentrant, with hidden internal state, etc. One such function is strtok() from <string.h>.

how to print memory bits in c

I'm learning how numbers are represented in memory. I want to know how to print the actual representation (binary or hexadecimal) in memory of some int and float variables.
I'd like to see what happens with that numbers when adding or subtracting it causes overflow, for example.
How can I access memory and print it?
You would need to assign a pointer to the variable in question to a char *, and treat it as an array of bytes of length sizeof(variable). Then you can print each byte in hex using the %X format specifier to printf.
You can define a function like this:
void print_bytes(void *ptr, int size)
{
unsigned char *p = ptr;
int i;
for (i=0; i<size; i++) {
printf("%02hhX ", p[i]);
}
printf("\n");
}
And call it like this:
int x = 123456;
double y = 3.14;
print_bytes(&x, sizeof(x));
print_bytes(&y, sizeof(y));
... to print the actual representation (binary ...
To convert any variable/object to a string that encodes the binary form uses a helper function that converts memory into a "binary" string. This method also handles function pointers. Uses C99 or later.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
// .... compound literal .......
#define VAR_TO_STR_BIN(x) obj_to_bin((char [sizeof(x)*CHAR_BIT + 1]){""}, &(x), sizeof (x))
char *obj_to_bin(char *dest, void *object, size_t osize) {
const unsigned char *p = (const unsigned char *) object;
p += osize;
char *s = dest;
while (osize-- > 0) {
p--;
unsigned i = CHAR_BIT;
while (i-- > 0) {
*s++ = ((*p >> i) & 1) + '0';
}
}
*s = '\0';
return dest;
}
int main(void) {
int i = 42;
double d = 3.1415926535897932384626433832795;
printf("Sample\ndouble pi:%s\nint 42:%s\n", VAR_TO_STR_BIN(d), VAR_TO_STR_BIN(i) );
return 0;
}
Output (Note: depending in endian-ness, results may vary)
Sample
double pi:0100000000001001001000011111101101010100010001000010110100011000
int 42:00000000000000000000000000101010
This approach is easy to adapt to hexadecimal form.
Let's say you have a int variable called memory. Make sure you see how many bits it is; for many processors an int is 32 bits as well as a memory address. So you need to loop through each bit, like this:
unsigned int memory = 1234;
for (int i = 0; i < 32; i++)
{
printf("%d ", memory >> i & 1);
}
This simple method ORs each bit with 1 and shifts each bit by 1.
#include <stdio.h>
#include <stdlib.h>
void print_bits ( void* buf, size_t size_in_bytes )
{
char* ptr = (char*)buf;
for (size_t i = 0; i < size_in_bytes; i++) {
for (short j = 7; j >= 0; j--) {
printf("%d", (ptr[i] >> j) & 1);
}
printf(" ");
}
printf("\n");
}
int main ( void )
{
size_t n;
scanf("%d", &n);
print_bits(&n, sizeof(n));
return 0;
}
This prints bits of the specified object (n here) with the specified size (in bytes).
#dbush, #Anton, I mixed your codes. It's okay?
#include <stdio.h>
#include <stdlib.h>
void print_bytes( void *ptr, size_t size ) ;
int main( void )
{
int x = 123456 ;
double y = 3.14 ;
print_bytes( &x, sizeof(x) ) ;
print_bytes( &y, sizeof(y) ) ;
return 0 ;
}
void print_bytes( void *ptr, size_t size )
{
//char *buf = (char*) ptr;
unsigned char *p = ptr ;
for( size_t i = 0; i < size; i++ )
{
printf( "%02hhX ", p[i] ) ;
}
printf( "\n" ) ;
for( size_t i = 0; i < size; i++ )
{
for( short j = 7; j >= 0; j-- )
{
printf( "%d", ( p[i] >> j ) & 1 ) ;
}
printf(" ");
}
printf("\n");
}
Call print_bits(memory address of variable, size of variable in byte).
void print_bits(void *ptr, int size) //ptr = memory address of variable, size = size of variable in byte
{
long long *ch = ptr;
int size_bits = size * 8;
for(int i = size_bits-1; i>=0; i--){
printf("%lld", *ch >> i & 1) ;
}
}
It has been tested successfully, working with any variable of less than or equal to 64 bits. This will probably work correctly with variables with other sizes (Not Tested).
Calling:
double d = -7.92282286274e+28;
print_bits(&d, sizeof(d));
Output:
1100010111110000000000000000000011100000000000000000000100010111

Free dynamically created 3d array in C

None of the answers I have found seem to address my issue. I am creating a dynamic 3d array in C and later freeing it. I can store and later access the data stored in this array using a nested for loop but I get an access violation when trying to free it using the same nested for loop setup. Where am I going wrong?
unsigned char ***buff1;
int r, c;
someFunction(&buff1, &r, &c);
for(int i = 0; i < r; ++i)
{
for(int j = 0; j < c; ++j)
{
free(buff1[i][j]);
}
free(buff1[i]);
}
free(buff1);
someFunction(unsigned char**** buff, int *nR, int *nC)
{
...
*buff = (SQLCHAR***)malloc(*nR * sizeof(SQLCHAR**));
for(int i = 0; i < *nR; ++i)
{
(*buff)[i] = (SQLCHAR**)malloc(*nC * sizeof(SQLCHAR**));
for(int j = 0; j < *nC; ++j)
{
(*buff)[i][j] = (SQLCHAR*)malloc(256);
}
}
}
Multiple things are wrong:
unsigned char**** buff
What is this, if not wrong? (Well, OK, not technically, but stylistically anyway...)
(SQLCHAR*)malloc(256);
isn't any better either, since you must not cast the return value of malloc() in C.
The third mistake is that you don't have a 3D array. You have a pointer-to-pointer-to-pointer. Ewww. Ugly. Why not allocate a true 3D array instead?
size_t xsize, ysize, zsize; // initialize these!
unsigned char (*arr)[ysize][zsize] = malloc(sizeof(*arr) * xsize);
Then all you need to do in order to free it is:
free(arr);
Honestly, isn't this way better?
I try you code in this way,and it works good:
#include "stdio.h"
#include "stdlib.h"
int someFunction (unsigned char**** buff, int *nR, int *nC)
{
int i,j;
*buff = (unsigned char ***)malloc(*nR * sizeof(char**));
for(i = 0; i < *nR; ++i)
{
(*buff)[i] = (unsigned char**)malloc(*nC * sizeof(char**));
for(j = 0; j < *nC; ++j)
{
(*buff)[i][j] = (unsigned char*)malloc(256);
(*buff)[i][j][0] ='1';
}
}
}
int main()
{
unsigned char ***buff1;
int r = 3, c= 2,i,j;
someFunction(&buff1, &r, &c);
for( i = 0; i < r; ++i)
{
for(j = 0; j < c; ++j)
{
printf(" %c",buff1[i][j][0]);
free(buff1[i][j]);
}
free(buff1[i]);
}
free(buff1);
}
So, maybe the mistake is not happening in the code you are showing to us.
Your code looks pretty buggy. For starters you are calling someFunction(&buff1, &r, &c) while that function expects ints and not int *s. Later you dereference nR and nC and they aren't pointers.
I guess you should be getting some nasty warnings when compiling.

Resources