I'm trying to make a code which converts some decimal numbers to bits.
There are more simple ways to reach this result but I'm poking around and joking with memory in C.
int ** decimalToBits(int *number,int size){
int **bits = (int **)malloc(sizeof(*bits)*size), i = 0;
for (int j = 0; j < size; j++) {
int * temp = (int *)malloc(sizeof(int));
while (number[j] >= 1) {
temp[i++] = number[j] % 2;
number[j] /= 2;
realloc(temp, sizeof(int));
}
printf("\n");
bits[j] = (int *) malloc(sizeof(int)*i);
for (int k = i-1; k >= 0; k--){
bits[j][k] = temp[k];
printf("%d" ,bits[j][k]);
}
i = 0;
}
return bits;
}
I'm having some allocation problems, first of all I'm going to explain the idea:
I pass to the function multiple numbers, so for example:
int numbers[2] = {23,73};
decimalToBits(numbers,2);
Each converted number will be stored in **bits double pointer, so bits[0] will contain the number 23 converted, and bits[1] will contain 73 converted as well.
The problem shows up when I do bits[j] = (int *) malloc(sizeof(int)*i); call,
because this seems to let the temp pointer to be overwritten with some random numbers. In fact if I remove the bits[j] = (int *) malloc(sizeof(int)*i); and bits[j][k] = temp[k]; lines and I replace printf("%d" ,bits[j][k]); with printf("%d" ,temp[k]);
the code seems to have a good behavior, and it gives me the correct output:
10111
1001001
I also noticed that allocating the bits[j] = (int *) malloc(sizeof(int)*8); externally from the for (int j = 0; j < size; j++) loop let the code works. So why this allocation problem occurs when declared just like the above code and what's the best way to solve it?
Related
This problem bothered me for an hour when I was programming, but I still didn't know the error of the original method after solving it.
void generate_r_vector(char (*r_vector)[17],char *random_r) {
BIGNUM* vector[127];
char r_v[128][17];
char flag[17];
memset(flag, 0, sizeof(flag));
int bits = 128;
int top = 0;
int bottom = 0;
for (int i = 0; i < 127; i++) {
vector[i] = BN_new();
BN_rand(vector[i], bits, top, bottom);
memset(r_v[i], 0, sizeof(r_v[i]));
BN_bn2bin(vector[i], r_v[i]);
}
memset(r_v[127], 0, sizeof(r_v[127]));
for (int i = 0; i < 127; i++) {
for (int j = 0; j < 16; j++) {
flag[j] = flag[j] ^ r_v[i][j];
}
}
for (int i = 0; i < 16; i++) {
r_v[127][i] = flag[i] ^ random_r[i];
}
for (int i = 0; i < 128; i++) {
memcpy(r_vector[i], r_v[i], 17);
}
}
Using memcpy to copy these arrays, when XOR in the main function, you can get the original string random_r.
But using the strcpy function to copy these arrays in the main function XOR, can not get the original random_r.
What I learned about OpenSSL:here, a 128 bit large number is converted into binary, and then every 4 bits are converted into a decimal, which is stored in the char array.
Memcpy copies by byte, while strcpy can only copy strings.
I can't understand why the XOR results of the two copy methods are different when they are both stored in char arrays.
My English level is not good, I hope you programmers can understand my expression. I sincerely hope you can answer my question. thank you
=======================2021/2/21 updata=====================================
I provide a program that can run directly, hoping to alleviate the problems caused by my unclear expression.
int main() {
char* random_r="1234567891234567";//长度16 算上'\0'17
char r_vector[128][17];
BIGNUM* vector[127];
char r_v[128][17];
char flag[17];//判断是否一致
memset(flag, 0, sizeof(flag));
int bits = 128;
int top = 0;
int bottom = 0;
for (int i = 0; i < 127; i++) {
vector[i] = BN_new();
BN_rand(vector[i], bits, top, bottom);
memset(r_v[i], 0, sizeof(r_v[i]));
BN_bn2bin(vector[i], r_v[i]);
}
memset(r_v[127], 0, sizeof(r_v[127]));
for (int i = 0; i < 127; i++) {
for (int j = 0; j < 16; j++) {
flag[j] = flag[j] ^ r_v[i][j];
}
}
for (int i = 0; i < 16; i++) {
r_v[127][i] = flag[i] ^ random_r[i];
}
//至此生成了128个向量,这些向量的异或之和正好是random_r的值,ans可以验证这个结论
char ans[17];
memset(ans, 0, sizeof(ans));
for (int i = 0; i < 128; i++) {
for (int j = 0; j < 16; j++) {
ans[j] = ans[j] ^ r_v[i][j];
}
}
printf("the target XOR result is:%s\n", ans);//
//下面使用memcpy的形式拷贝并求异或值
for (int i = 0; i < 128; i++) {
memcpy(r_vector[i], r_v[i], 17);//逐字节拷贝解决问题strcpy会出现问题,原因未知
}
memset(ans, 0, sizeof(ans));
for (int i = 0; i < 128; i++) {
for (int j = 0; j < 16; j++) {
ans[j] = ans[j] ^ r_vector[i][j];
}
}
printf("using memcpy copying and the result is:%s\n", ans);//这是正确的结果
memset(r_vector, 0, sizeof(r_vector));
for (int i = 0; i < 128; i++) {
strcpy(r_vector[i], r_v[i]);//strcpy会出现问题,原因未知
}
memset(ans, 0, sizeof(ans));
for (int i = 0; i < 128; i++) {
for (int j = 0; j < 16; j++) {
ans[j] = ans[j] ^ r_vector[i][j];
}
}
printf("using strcpy copying and the result is:%s\n", ans);
int err_count = 0;
for (int i = 0; i < 128; i++) {
if (strcmp(r_vector[i], r_v[i]) != 0) err_count++;
}
printf("after using strcpy() each vector using strcmp() with orignal r_v,the different vector nums:%d\n", err_count);
system("pause");
return 0;
}
Running results in vs2019
the target XOR result is:1234567891234567
using memcpy copying and the result is:1234567891234567
using strcpy copying and the result is:12eH⊙碡?H-c纫
after using strcpy() each vector using strcmp() with orignal r_v,the different vector nums:0
What causes the difference between memcpy and strcpy in copying openssl BIGNUM
The comment "BIGNUM values are not C strings, so strcpy() won't work." may be not enough to enlighten you.
BIGNUM values can contain a byte with all bits set to 0, called the null character, and since that is used to terminate a character string, strcpy() stops there and doesn't copy the rest of the BIGNUM value.
Even when strcpy and memcpy are both used for char arrays, they don't do exactly the same thing. memcpy copies a fixed number of bytes, which you give as the third argument. strcpy doesn't just copy from one char array or pointer to another, it figures out how much to copy in a completely different way, namely by checking for a 0 value in the chars to copy.
Even though r_vector points to char arrays, they don't have to be strings: If they are not 0-terminated or have 0 values at other positions things will behave differently than for a string.
I'm trying to convert a decimal number, using C, and my function is doing the first part right, but not the second. It's supposed to get the remainder of the number divided by 2, store those numbers in an array, and return the array but reversed. My code is:
int* showbits(int decNum){
int originalBits[32];
int i;
for(i = 0; i < 32; i++){
int temp = decNum % 2;
originalBits[i] = temp;
decNum = decNum / 2;
}
int a;
for (a = 0; a < 32; a++){
printf("%d ", originalBits[a]);
}
printf("\n");
int j = 0;
int k = 32;
int bits[32];
for (j = 0; j < 32; j++){
for (k = 32; k > 0; k--){
bits[j] = originalBits[k];
}
}
int m;
for (m = 0; m < 32; m++){
printf("%d ", bits[m]);
}
return bits;
}
The output puts all 1s if I feed the function 255. I also tried replacing the last loop with:
for (j = 0; j < 32; j++){
bits[j] = originalBits[k--];
}
but this misses a number and for 255, gives 1111111 instead of 11111111
This does not make sense at all:
for (j = 0; j < 32; j++)
{
for (k = 32; k > 0; k--)
{
bits[j] = originalBits[k];
}
}
I think you want to reverese here, but think about what you are doing.
You are using one loop iteration of j to write every element of originalBits to bits[0] then you do the same to bits[1] and continue on. This means at the end every value of bits has the value of originalBits[0].
One loop is sufficent here, you just have to start reading from the otherside of the array:
for (j = 0; j < 32; j++)
{
bits[j] = originalBits[31-j];
}
This way you read from the end of originalBits to the front and write to the front of bits to the end. Enough to reverse the content.
Other than that you can not return a pointer to an array that is local to the function.
int bits[32];
will be invalid as soon as you reach the end of the function, yet you pass the address of it to the caller. This is undefined behaviour and has tobe avoided.
Either you create an array with static storage duration, for example by declaring it in file scope as a global variable.
Or you could use malloc to get memory dynamically,
int *bits = malloc(32 * sizeof *bits);
but the you have to make sure you also free the allocated memory.
Another possibility would be declaring the array in main and passing the address to the function then you would be able to write to it and you would not even have to return anything.
Regarding your version 1:
At the end of your inner loop, k is always 0.
for (j = 0; j < 32; j++){
for (k = 32; k > 0; k--){
bits[j] = originalBits[k];
}
}
This means that each bits[j] will hold the value of originalBits[0] after the nested loops.
Solution:
for (j = 0; j < 32; j++){
bits[j] = originalBits[31-j];
}
Regarding your version 2:
You start with k=32 and decrement after using it in each iteration:
for (j = 0; j < 32; j++){
bits[j] = originalBits[k--];
}
This means you will end up with originalBits[32] ... originalBits[1] in your array.
This is an out of bounds access and also missing the last element.
A solution would be like this:
for (j = 0; j < 32; j++){
bits[j] = originalBits[31-j];
}
As a general hint:
This type of error can be easily spotted using a debugger. Step through your loops, watch your index variables, fix it.
Update regarding returning pointer to non-static array:
int* showbits(int decNum)
{
int bits[32];
...
return bits;
}
Here bits will become invalid after the function is left. This makes your pointer invalid.
You can solve this in different ways:
If you function is not called simultanously from multiple threads or for multiple value before the array is used:
int* showbits(int decNum)
{
static int bits[32];
...
return bits;
}
Now the array will keep valid and your pointer as well. If you call the function again, the same array is used, changing bits from previous calls.
If you need different buffers:
int* showbits(int decNum)
{
int *bits = malloc(sizeof(*bits)*32);
...
return bits;
}
Then you need to free the pointer afterwards in the calling function.
I have to make a program that sort strings (with exact length 7 chars) by using radix sort. I already made a function that sort each column separately. My problem is how to make the whole string move, not just one char. It's really problematic for me to see how should it work in C.
I made one array "char strings[3][8]" and "char output[3][8]" to get sorted 3 strings with exact 7 chars in each one. For example sorting these strings:
strcpy(strings[0], "kupbars");
strcpy(strings[1], "daparba");
strcpy(strings[2], "jykaxaw");
In output I get:
dakaaaa
juparbs
kypbxrw
Each column is sorted correctly but chars don't stick together. I tried many ways for 3 hours but nothing works.
My code looks like this:
void countingSort(char a[][8], char b[][8]) {
int c[123];
for (int pos = 6; pos >= 0; pos--) {
for (int i = 0; i < 123; i++)
c[i] = 0;
for (int i = 0; i < 3; i++)
c[(int)a[i][pos]]++;
for (int i = 1; i < 123; i++)
c[i] += c[i - 1];
for (int i = 2; i >= 0; i--) {
b[--c[(int)a[i][pos]]][pos] = a[i][pos];
}
}
}
(There are constants limiting string length etc. because it's easy to change it to variable - I just focused on getting this program work properly.)
Try changing the loop to move an entire string:
for (int i = 2; i >= 0; i--) {
int k = --c[(int)a[i][pos]];
for(int j = 0; j < 8; j++) {
b[k][j] = a[i][j];
}
}
You could do a circular list but it's a little overhead. I propose you to use memmove().
#include <string.h>
void array_move_forward(char array[3][8]) {
for (int i = 0; i < 3; i++) {
char tmp = array[i][6];
memmove(array[i] + 1, array[i], 6);
array[i][0] = tmp;
}
}
void array_move_rewind(char array[3][8]) {
for (int i = 0; i < 3; i++) {
char tmp = array[i][0];
memmove(array[i], array[i] + 1, 6);
array[i][6] = tmp;
}
}
A other solution would be to manipulate your string yourself and using a index, that indicate the first letter of your string.
{
char str[7];
int i = 0;
...
int j = i;
for (int k = 0; k < 7; k++) {
char tmp = str[j++ % 7];
}
}
With that you could rotate your string just with i++ or i--.
struct my_string_radix {
char str[7];
int begin;
}
Array initialization Code:
int m = 100;
int n = 50;
int i = 0, j = 0;
float **a = (float**)malloc(m*sizeof(float*));
for (i = 0; i < m; i++)
{
a[i] = (float*)malloc(n*sizeof(float));
for (j = 0; j < n; j++)
a[i][j] = i + j;
}
a is a 2D array and I want to traverse and update the elements of the 1D array a[0]
Say I want to divide all elements of a[0] by 2:
for (i = 0; i < n; i++)
*a[0]++ /= 2; // instead of a[0][i] /= 2;
This doesn't seem to work..
I guess a is a 2 dimensional array like int a[10][20], then the given statement a[i]++ is "invalid".
The reason is that since a[i] being an array a[i] is a non-modifiable 'lvalue'.
In the above case *a[i] is valid but not the a[i]++
Yes, although it look like a homework. If you want more interesting code, you could write this without spaces, as *a[i]++/=K, and finally you could attach this to the containing loop, as for example while(p=a[i]++)*p/=K; to make things more compressed. ;-)
I'm trying to multiply two multidimensional arrays to form a matrix. I have this function. This should work in theory. However, I am just getting 0s and large/awkward numbers. Can someone help me with this?
int **matrix_mult( int **a, int **b, int nr1, int nc1, int nc2 )
{
int **c;
int i,j,k,l;
c = malloc(sizeof(int *)*nr1);
if (c == NULL){
printf("Insuff memm");
}
for(l=0;l<nr1;l++){
c[l] = malloc(sizeof(int)*nc1);
if (c[l] == NULL){
printf("Insuff memm");
}
}//for loop
for (i=0;i<nr1;i++){
for (j=0;j<nc2;j++){
for (k=0;k<nc1;k++){
c[i][j] = (a[i][k]) * (b[k][j]);
}
}
}
return( c );
}
Are you doing mathematical matrix multiplication? If so shouldn't it be:
for(i = 0; i < nr1; i++)
{
for(j = 0; j < nc1; j++)
{
c[i][k] = 0;
for(k = 0; k < nc2; k++)
{
c[i][k] += (a[i][j]) * (b[j][k]);
}
}
}
My full and final solution, tested to produce sensible results (I didn't actually do all the calculations myself manually to check them) and without any sensible niceties such as checking memory allocations work, is:
int **matrix_mult(int **a, int **b, int nr1, int nc1, int nc2)
{
int **c;
int i, j, k;
c = malloc(sizeof(int *) * nr1);
for (i = 0; i < nr1; i++)
{
c[i] = malloc(sizeof(int) * nc2);
for (k = 0; k < nc2; k++)
{
c[i][k] = 0;
for (j = 0; j < nc1; j++)
{
c[i][k] += (a[i][j]) * (b[j][k]);
}
}
}
return c;
}
There were a few typos in the core of the for loop in my original answer, mostly due to my being mislead by a different answer. These have been corrected for posterity.
If you change c[i][j] = (a[i][k]) * (b[k][j]); to c[i][j] += (a[i][k]) * (b[k][j]); in your code then it will work just fine provided that
nr1 is number of rows of matrix a
nc1 is the number of columns of the matrix a
nc2 is the number of columns of the matrix b
Just be sure that the matrix c is initiated with zeroes. You can just use calloc instead of malloc when allocating space, or memset the allocated array after a call to malloc.
One more tip is to avoid using the letter l when accessing array elements. when tired, you will have hard time noticing errors with l vs 1.