1

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

wohlstad
  • 12,661
  • 10
  • 26
  • 39
BOGDAN DONICI
  • 79
  • 1
  • 1
  • 8
  • The code you've posted is nice and compact, but doesn't compile. Please [edit] your question to include a [mcve]. – Sneftel Jul 11 '22 at 08:21
  • 1
    https://stackoverflow.com/questions/72436704/what-are-null-terminated-strings – n. m. could be an AI Jul 11 '22 at 08:38
  • Hint: How does printf know how long the string is? – user253751 Jul 11 '22 at 09:21
  • Welcome to StackOverflow. If an answer solves your problem you could click '✔' to mark it as an acceptable answer. You can also upvote any helpful answer (see here: https://stackoverflow.com/help/someone-answers). – wohlstad Jul 11 '22 at 12:28

3 Answers3

2

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; 
}
Gerhard
  • 6,850
  • 8
  • 51
  • 81
HEllRZA
  • 287
  • 1
  • 7
  • Yeah! But why my L that have a size of 32 is filled up to 64 characters? The for runs assigns the value till i become 31 – BOGDAN DONICI Jul 11 '22 at 08:26
  • @BOGDANDONICI Where do you see it filled up with 64 characters? If there is no `\0` byte after the 32 characters, `printf` will just continue in adjacent memory until it finda a `\0` byte, no matter which variable is the memory belonging to. – Gerhardh Jul 11 '22 at 08:29
  • So what should I do? Simply increment the size of the array by one and fill the position L[32] with ‘\0’? – BOGDAN DONICI Jul 11 '22 at 08:36
  • @BOGDANDONICI Yes, see the edit of Gerhardh (thanks!) – HEllRZA Jul 11 '22 at 09:13
  • 1
    That was the edit of another Gerhard ;) – Gerhardh Jul 11 '22 at 10:42
  • @BOGDANDONICI Most likely, `R` comes immediately after `L` in memory since they're declared sequentially. And most likely, the first byte following the last value in `R` is coincidentally zero (zero is a common value in uninitialized memory. Volatile memory is zeroed out when the machine is rebooted, and some platforms zero-out memory when freed). In other words, there might "accidentally" be a zero following `R`. Zero is the null terminator, so when you print `L`, it's probably starting at `L` and continuing all the way through `R` until it hits that accidental null terminator. But it's UB. – Alexander Guyer Aug 11 '22 at 16:52
0

Using printf with "%s" assumes the value is a zero terminated string (AKA NULL 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):

1. 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';

2. 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.).

wohlstad
  • 12,661
  • 10
  • 26
  • 39
0
  • 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);
}
Lundin
  • 195,001
  • 40
  • 254
  • 396