Home > Mobile >  Why C dosen't split correctly arrays?
Why C dosen't split correctly arrays?

Time:07-11

I have an array of 64 characters, which I need to divide into two parts, the left part of 32 characters and the right part, also 32 characters.

char *IP_M; // 64 characters array
char L[32]; // left part
char R[32]; // right part

The IP_M array is filled in as follow:

char *start_inital_permutation(const char *input) {
    char *output = malloc(64 * sizeof(char));
    for (int i = 0; i < 8; i  ) {
        for (int j = 0; j < 8; j  ) {
            output[i * 8   j] = input[IP[i][j] - 1];
        }
    }
    return output;
}
...
IP_M = start_inital_permutation(M);

where M is also a 64 characters string. With the following method I tried to fill the other two array (L, R) by spliting the IP_M.

void fill_LR() {
    for (int i = 0; i < 32; i  ) {
        L[i] = IP_M[i];
        R[i] = IP_M[i   32];
    }
}

but when I run the following instructions:

printf("IP_M: %s\n", IP_M);
printf("L: %s\n", L);
printf("R: %s\n", R);

the output is:

IP_M: 1100110000000000110011001111111111110000101010101111000010101010
L: 1100110000000000110011001111111111110000101010101111000010101010
R: 11110000101010101111000010101010

I can't get out of this situation, can someone help me please?

*EDIT: also tried the memcpy() method but it still not work! Here is the Project if someone want to see it: https://github.com/ionutbogdandonici/DES_C.git

CodePudding user response:

Strings in C are \0 terminated. So the print function will print the string until it reaches the \0 character.

Assign space for null:

char L[33]; // left part
char R[33]; // right part

Add null terminator:

void fill_LR() {
    for (int i = 0; i < 32; i  ) {
        L[i] = IP_M[i];
        R[i] = IP_M[i   32];
    }
    L[32] = 0;
    R[32] = 0; 
}

CodePudding user response:

  • output[i * 8 j] = input[IP[i][j] - 1]; is gibberish.
  • Strings in C are null terminated but you never allocate space for a null terminator anywhere, nor do you null terminate your strings.
  • Don't use global variables.

I was able to salvage your program like this:

#include <stdio.h>
#include <stdlib.h>

char *start_inital_permutation(const char *input) {
    size_t count=0;
    char *output = malloc(64 * sizeof(char)   1);
    for (int i = 0; i < 8; i  ) {
        for (int j = 0; j < 8; j  ) {
            output[i * 8   j] = input[count  ];
        }
    }
    output[64] = '\0';
    return output;
}

int main()
{
    const char input[] = "1100110000000000110011001111111111110000101010101111000010101010";
    char *IP_M = start_inital_permutation(input);
    char L[32 1]; // left part
    char R[32 1]; // right part
    for (int i = 0; i < 32; i  ) {
        L[i] = IP_M[i];
        R[i] = IP_M[i   32];
    }
    L[32] = '\0';
    R[32] = '\0';

    printf("IP_M: %s\n", IP_M);
    printf("L:    %s\n", L);
    printf("R:    %s\n", R);
}

However, there's no apparent reason why you need to do the middle step with the 64 characters array. You could as well put that one in a union and save the copy (although then the individual left/right strings won't be null terminated). Example:

#include <stdio.h>
#include <stdlib.h>

typedef union
{
  char data [64 1];
  struct
  {
    char left[32];
    char right[32];
    char zero;
  };
} ip_t;

ip_t *start_inital_permutation(const char *input) {
    size_t count=0;
    ip_t* obj = malloc(sizeof(ip_t));
    for (int i = 0; i < 8; i  ) {
        for (int j = 0; j < 8; j  ) {
            obj->data[i * 8   j] = input[count  ];
        }
    }
    obj->data[64] = '\0';
    return obj;
}

int main()
{
    const char input[] = "1100110000000000110011001111111111110000101010101111000010101010";
    ip_t *IP_M = start_inital_permutation(input);

    printf("IP_M: %s\n", IP_M->data);
    printf("L:    %.32s\n", IP_M->left);
    printf("R:    %.32s\n", IP_M->right);
}

CodePudding user response:

Using printf with "%s" assumes the value is a zero terminated string.
I.e. a pointer to a sequence of chars, ending with a \0 char.

In your case when printf attempts to print L it prints char, and after the 32 chars that belong to L it continues. It happened to be that R is following L in memory, and so the content of R is also dumped. If the next byte in memory following R was not a 0, you would see even more characters printed. This behavior is dependent on the [possibly atrbitarary] content of your memory.

How to handle the issue (2 ways):

You can either increase the size of L and R to 33, and assign the last char to \0:

char L[33]; // left part
char R[33]; // right part
/* ... */
L[32] = '\0';
R[32] = '\0';

Or specify to printf the length of the strings (32) like this:

/*----------vvv-------*/ 
printf("L: %.32s\n", L);
printf("R: %.32s\n", R);

In the later case keep in mind that L and R are not "regular" C strings, which are expected to be zero terminated (at least as far as it concerns common functions like strlen, strcmp etc.).

  • Related