With char *key = argv[2];
, the cast (int) key
does not reinterpret the contents of that string as a valid integer. What that cast does is take the pointer value of key
, and interprets that as an integer. The result of this is implementation-defined, or undefined if the result cannot be represented in the integer type (a likely outcome if sizeof (int) < sizeof (char *)
).
The C standard does not define any meaning for these values.
Here is a test program that, depending on your platform, should give you an idea of what is happening (or failing to happen)
#include <stdio.h>
int main(int argc, char **argv) {
if (sizeof (long long) >= sizeof (char *))
printf("Address %p as an integer: %lld (%llx)\n",
(void *) argv[0],
(long long) argv[0],
(long long) argv[0]);
}
As an example of implementation-defined behaviour, on my system this prints something like
Address 0x7ffee6ffdb70 as an integer: 140732773948272 (7ffee6ffdb70)
On my system, casting that same pointer value to (int)
results in undefined behaviour.
Note that intptr_t
and uintptr_t
are the proper types for treating a pointer value as an integer, but these types are optional.
To actually convert a string to an integer, you can use functions such as atoi
, strtol
, or sscanf
. Each of these have their pros and cons, and different ways of handling / reporting bad input.
Examples without error handling:
int three = atoi("3");
long four = strtol("4", NULL, 10);
long long five;
sscanf("5", "%lld", &five);
number_to_alphabet_string
has a few problems.
malloc
can fail, returning NULL
. You should be prepared to handle this event.
In the event malloc
succeeds, the contents of its memory are indeterminate. This means that you need to initialize (at least partially) the memory before passing it to a function like strcat
, which expects a proper null terminated string. As is, strcat(str, arr);
will result in undefined behaviour.
Additionally, memory allocated by malloc
should be deallocated with free
when you are done using it, otherwise you will create memory leaks.
char *foo = malloc(32);
if (foo) {
foo[0] = '\0';
strcat(foo, "bar");
puts(foo);
free(foo);
}
In general, strcat
and the additional buffers are unnecessary. The use of char arr[8];
in particular is unsafe, as arr[i] = buffer[i];
can easily access the array out-of-bounds if n
is large enough.
Additionally, in strcat(str, arr);
, arr
is also never null terminated (more UB).
Note also that printf(str);
is generally unsafe. If str
contains format specifiers, you will again invoke undefined behaviour when the matching arguments are not provided. Use printf("%s", str)
, or perhaps puts(str)
.
As far as I can tell, you simply want to translate your integer value n
into the uppercase character it would be associated with if A=1, B=2, ... and repeat it n
times.
To start, there is no need for buffers of any kind.
void number_to_alphabet_string(int n) {
if (1 > n || n > 26)
return;
for (int i = 0; i < n; i++)
putchar('A' + n - 1);
putchar('\n');
}
When passed 5
, this will print EEEEE
.
If you want to create a string, ensure there is an additional byte for the terminating character, and that it is set. calloc
can be used to zero out the buffer during allocation, effectively null terminating it.
void number_to_alphabet_string(int n) {
if (1 > n || n > 26)
return;
char *str = calloc(n + 1, 1);
if (str) {
for (int i = 0; i < n; i++)
str[i] = 'A' + n - 1;
puts(str);
free(str);
}
}
Note that dynamic memory is not actually needed. char str[27] = { 0 };
would suffice as a buffer for the duration of the function.
A cursory main
for either of these:
#include <stdio.h>
#include <stdlib.h>
void number_to_alphabet_string(int n);
int main(int argc, char *argv[]) {
if (argc > 1)
number_to_alphabet_string(atoi(argv[1]));
}
Note that with an invalid string, atoi
simply returns 0
, which is indistinguishable from a valid "0"
- a sometimes unfavourable behaviour.