Home > Back-end >  Strlen, Malloc and address arithmetic
Strlen, Malloc and address arithmetic

Time:03-14

Need some help breaking down this C function. I'm stuck on the malloc line. I do not understand what the " 8" is doing and/or why it is even there. My research revealed it has something to do with address arithmetic. Also, I won't mind some help checking the rest of my breakdown (comments) of each line of code is correct.

    // Prints help message to the console
    // Returns a string
    char * helloWorld(char * name) {                                //The * is a pointer to an address. (char * name) = the address to a char pointer stored/passed via name.
        char * answer = malloc(strlen(name)   8);                   //syntax = (cast-type*) malloc(byte-size); answer has a * because malloc returns a void pointer. The * deferences the pointer
                                                                    //and tells the program to use the value at that member address.
                                                                    //strlen returns a 
        printf("This prints to the console when you Run Tests");
        strcpy(answer, "Hello, ");                                  //This returns a pointer to the destination string dest. char *strcpy(char *dest, const char *src)
                                                                //(answer {dest}, "Hello, "{string to be copied to dest}) *dest= The value at the pointer of src("Hello, ") will be assigned.
        strcat(answer {des}, name {src});               //char *strcat(char *dest, const char *src) --> appends the string pointed to by src to the end of the string pointed to by dest.
        return answer;                                  //adds name to the end of answer. -->Hello, name.
    }

CodePudding user response:

It has absolutely nothing to do with address arithmetic. strlen(name) 8 is just that; take the length name and add 8 to it.

8 is the magic number constituted of the length of the string Hello, (7 bytes) plus 1 more byte for the resulting string's null terminator.

CodePudding user response:

My research revealed it has something to do with address arithmetic.

That is wrong. There is no address arithmetic involved here.

You did not tell us what you would expect to see instead of the 8.

If you would use strlen(name) directly, there is no room for the terminating 0 byte.

And also there would only be room for copying name into the new memory. But you want to add "Hello, " at the begin of the memory area. That string takes 7 bytes.

In the end, 7 bytes for "Hello, " and 1 byte for terminating the string with a 0 byte, makes 8 bytes in total that you have to add when allocating memory.

CodePudding user response:

There's no pointer arithmetic at play here. The malloc function is being told to allocate strlen(name) 8 bytes of memory, i.e. enough for name plus an additional 7 characters and a null terminating byte.

The following lines copy the string "Hello, " to answer and then concatenates name onto it. The leading string "Hello, " has 7 characters, so that's what the extra 7 is for on the allocation.

CodePudding user response:

If you write to answer you must ensure, that it has enough space to fit the entire result string. Because this size is only needed at runtime, the space is malloced. (A second reason is that you return the address of it, so you can't have it on the stack).

If you look at the code you see, that the answer will be Hello, (length = 7) plus the name (length = strlen(name)) plus a terminating null byte (length = 1). So strlen(name) 8 will perfectly fit the answer.

CodePudding user response:

It needs enough memory for the input string (the result of strlen), a prefix "Hello, " (7 characters), and a terminating NUL character (1 character), thus adding 8 to the strlen to get the total required memory to allocate.

As you've noted, this is somewhat confusing (magic numbers often are), and fragile (each change to the prefix requires a matching change to the seemingly unrelated magic number), so in nicer code you might do something like:

// Prints help message to the console
// Returns a string
char * helloWorld(char * name) {                                //The * is a pointer to an address. (char * name) = the address to a char pointer stored/passed via name.
    static const char PREFIX[] = "Hello, ";
    // Conveniently, the size of the array includes the NUL too
    char * answer = malloc(strlen(name)   sizeof(PREFIX));                   //syntax = (cast-type*) malloc(byte-size); answer has a * because malloc returns a void pointer. The * deferences the pointer
                                                                //and tells the program to use the value at that member address.
                                                                //strlen returns a 
    printf("This prints to the console when you Run Tests");
    strcpy(answer, PREFIX);                                  //This returns a pointer to the destination string dest. char *strcpy(char *dest, const char *src)
                                                            //(answer {dest}, "Hello, "{string to be copied to dest}) *dest= The value at the pointer of src("Hello, ") will be assigned.
    strcat(answer {des}, name {src});               //char *strcat(char *dest, const char *src) --> appends the string pointed to by src to the end of the string pointed to by dest.
    return answer;                                  //adds name to the end of answer. -->Hello, name.
}

which makes it clear why you're increasing the length of the allocation without magic numbers not directly tied to the prefix itself.

CodePudding user response:

8 here has nothing to do with pointer arithmetic as other answers have mentioned. Inside malloc you specify the number of bytes you would like to allocate in the memory. strlen(name) is the number of char in the name string, and 8 is the number of bytes of the string literal "Hello, " including a null terminator.

As of this line of comment, char * does not dereference the void pointer. It is a variable declaration for char*, where the right hand side can be implicitly converted to char*.

char * answer = malloc(strlen(name)   8); // syntax = (cast-type*) malloc(byte-size); answer has a * because malloc returns a void pointer. The * deferences the pointer

CodePudding user response:

It is supposed that the fucntion must return a string like for example

"Hello, N6DYN"

where the name "N6DYN" is passed to the function through the parameter name.

So the magic number 8 means the size of the string "Hello, " that is stored in memory like

{ 'H', 'e', 'l', 'l', 'o', ',', ' ', '\0' }

The function can be declared and defined the following way as it is shown in the demonstration program below

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

char * helloWorld( const char * name ) 
{
    const char *hello = "Hello, ";

    char *answer = malloc( strlen( name )   strlen( hello )   1 );                           

    if ( answer != NULL )
    {
        strcpy( answer, hello );                                                                           
        strcat( answer, name );
    }

    return answer;
}

int main( void )
{
    char name[100] = "";

    printf( "Enter your name: " );

    scanf( "           
  • Related