1

The output should be "the wallet belongs to Warren Buffett with balance of 85500000000" but I am getting "The wallet belongs to Warren Buffett with balance of 0.000000". Can you please let me know where am I making the mistake?

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

typedef struct {
    char *owner;
    long double balance;
} Wallet;

int main(int argc, char **argv) {
    const char *owner = "Warren Buffett";
    Wallet *wallet = (Wallet *) malloc(sizeof(Wallet));
    wallet->owner = (char *) malloc(strlen(owner) * sizeof(char));
    strcpy(wallet->owner, "Warren Buffett");
    wallet->balance = 85500000000;
    printf("The wallet belongs to %s with balance of %Lf",
           wallet->owner, wallet->balance);

    return 0;
}
Axifive
  • 1,159
  • 2
  • 19
  • 31
  • 3
    You don't malloc enough space - strings have a null terminator – M.M Aug 09 '21 at 23:14
  • 2
    also if you are using GCC in Windows, [see here](https://stackoverflow.com/questions/1764350/conversion-specifier-of-long-double-in-c) – M.M Aug 09 '21 at 23:16
  • @Axifive: Try with AddressSanitizer and you'll see [not so much](https://godbolt.org/z/rMbqeM5dG). Can onlinegdb enable ASan? – Nate Eldredge Aug 09 '21 at 23:33
  • An off-topic warning about using floating point numbers for currency: you shouldn't. Floating point numbers are approximations with unexpected edge cases (e.g `(0.1 + 0.2) == 0.3` is `false`). Better to use the smallest quantity (e.g. cents or 1/00 of a cent or whatever is appropriate) and use well established banking rounding rules when multiplying or dividing. – John Bayko Aug 09 '21 at 23:59
  • 1
    Remember, for future sake, to always `free()` what you `malloc()`. In the code above (no recursion, no loops, no functions except `main()`, ...) there's no big harm by leaving the memory marked as "in use" when the program terminates. – pmg Aug 10 '21 at 08:30

1 Answers1

3

You're not allocating enough space for wallet->owner.

Strings in C consist of a sequence of characters followed by a terminating null byte. You're allocating strlen(owner) * sizeof(char) bytes for wallet->owner which is enough for the characters in the string but not for the terminating null byte. As a result, you're writing past the end of allocated memory. This triggers undefined behavior, which can manifest as unexepected output.

Add 1 to the allocated space:

wallet->owner = malloc(strlen(owner) + 1);

Also, sizeof(char) is guaranteed to be 1 so the multiplication by that can be omitted, and you shouldn't cast the return value of malloc.

dbush
  • 205,898
  • 23
  • 218
  • 273