1

I would like to assign a value to a not initialised char*. The char* is global, so a char = "value" just gives me a dangling pointer. I have seen that strncpy could be a viable option. Is it possible that the size of the char* dynamicly changes to the assigned value? Because declaring it with a random high size does not feel right.

Thanks in advance :)

Edit 1:

char* charName[100];

method(anotherChar) {
strncpy(charName, anotherChar, strlen(anotherChar));
}

Is it possible to do this in a cleaner and safer way? It does not feel right to initalize charName with a length of 100, when the length of anotherChar is not known.

Edit 2:

char API_key;

void func(char* message) {
    if (waiting_for_user_input && message != NULL) {
    if (API_key == NULL) {
        API_key = (char*)malloc(strlen(message));
        strcpy(API_key, message);
    }
    else {
        API_key = (char*)realloc(API_key, strlen(message));
        strcpy(API_key, message);
    }
    waiting_for_user_input = false;
}

}

In this case I get warnings that "API_key" could be '0'. I do not really understand this warning, because I am checking if API_key is NULL and then handling both cases.

  • Is it going to change, and what values can it take on? – Neil Oct 03 '22 at 00:10
  • we need to see the relevant code – erik258 Oct 03 '22 at 00:12
  • 2
    `char = "value"` no, it doesn't. If that is really from your code that pointer isn't 'dangling' regardless of global or otherwise. Literals are global constant. *Real* code describes your preponderance better than you can alone. It should be included, minimal-yet-complete, *valid*, and should amplify your concern or confusion. – WhozCraig Oct 03 '22 at 00:15
  • 1
    @WhozCraig oh is does not? I thought so, because the global variable was not updated and set back to NULL after the method finished. Yes, i edited my question. – CodeEnjoyer Oct 03 '22 at 00:20
  • CodeEnjoyer, Please post a [mcve] that demos your goal and/or problem. As is, the problem description and code do not match well. – chux - Reinstate Monica Oct 03 '22 at 00:29
  • 5
    Even if that were a proper [mcve] (which it isn't), that first argument to `strncpy` should be puking warnings/errors from your compiler. You're sending a `char**` to a function expecting `char*`. I'm trying to understand what your actual *problem* you're trying to solve is. Are you looking to take a `char*` that is pointing to a *dynamic* string and extend (or contract) it? Change it do a different dynamic string? I see answers below that seem to guess at the problem, and provide solutions therefor. If we knew *exactly* what you're trying to do it would help immensely. – WhozCraig Oct 03 '22 at 00:39
  • This code and its description in the text is all-over-the-scenery... Any attempt to answer this OP must make assumptions... and we all know the consequence of "assuming" something... – Fe2O3 Oct 03 '22 at 01:05
  • 1
    Might I suggest a few links that provide basic discussions of pointers that may help. [Difference between char *pp and (char*) p?](https://stackoverflow.com/a/60519053/3422102) and [Pointer to pointer of structs indexing out of bounds(?)...](https://stackoverflow.com/a/60639540/3422102) (ignore the titles, the answers discuss pointer basics) – David C. Rankin Oct 03 '22 at 03:42
  • `char* charName[100]` is any of a 100 pointers to `char` it's not compatible with the standard function `strncpy` which wants to copy a string (i.e. array of characters). – Persixty Oct 03 '22 at 12:53
  • Hi, I'm voting to close because this is asking multiple questions. One about `strncpy` and another about `strcpy` and `malloc()`. I recommend deciding what you want to do any providing a mcve in a new question. – Persixty Oct 03 '22 at 12:57

2 Answers2

2

if you are worrying about the size of anotherChar, simple you can can convert the code:

char* charName[100];

method(anotherChar) {
    strncpy(charName, anotherChar, sizeOf(anotherChar));
}

into :

char *s = NULL;
void func(char* anotherChar){
    if(s != NULL)
        free(s);

    s = (char *) malloc(strlen(anotherChar) * sizeof(char) + 1);
    strcpy(s, anotherChar);
    
}

so every time, we free the old memory allocated in the heap using free(s); and then allocate a new memory in the heap by knowing the information of strlen(anotherChar) which is the length of the string to be assigned till the \0 but excluding \0 and sizeof(char) which is normally 1 byte and we add 1 to reserve a place for the null character at the end of the string.

and at last, we use strcpy(s, anotherChar); to copy all characters till \0 from one string to another.

and this is some text code:

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

char *s = NULL;
void func(char* anotherChar){
    if(s != NULL)
        free(s);

    s = (char *) malloc(strlen(anotherChar) * sizeof(char) + 1);
    strcpy(s, anotherChar);

}

int main(void) {

    func("hello");
    printf("s = %s\n", s);

    func("hi");
    printf("s = %s\n", s);

    func("Dummy text");
    printf("s = %s\n", s);


  return 0;
}

and this is the output:

s = hello
s = hi
s = Dummy text
abdo Salm
  • 1,678
  • 4
  • 12
  • 22
  • 2
    Notable: `sizeof(char)` is *always* `1`, and is therefore entirely optional. The only legitimate reason to include it is force-of-habit; when `malloc`ing `n` things, `n * sizeof(thing)` is the general vernacular. Also, [don't cast `malloc` in C programs](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Finally, if using a remotely-compliant POSIX platform, [`strdup`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html) will eliminate most of the code in `func`. `realloc` may also be incredibly helping here if used correctly. – WhozCraig Oct 03 '22 at 00:42
  • 1
    abdo Salm, `(strlen(anotherChar) * sizeof(char) + 1)` is _conceptually_ wrong. Should be `((strlen(anotherChar) + 1) * sizeof(char))` - scale `strlen(anotherChar)` and `1` by `sizeof(char)`. Yet since `char` is size 1, simplify to `(strlen(anotherChar) + 1)`. – chux - Reinstate Monica Oct 03 '22 at 02:35
  • BTW, watch out for the coding trap with `void func(char* anotherChar){ if(s != NULL) free(s); ...`. Consider what happens when code calls `func(s)`. – chux - Reinstate Monica Oct 03 '22 at 02:39
  • Thanks that helped. @WhozCraig i tried to implement it with realloc but i get some compiler warnings im not sure about. I am going to add it into my original question. – CodeEnjoyer Oct 03 '22 at 10:22
1

After creating a char* array of a certain size, you cannot change it. These strings have a limited length and you can't expand them. But you can create a longer string and then concatenate them.

char* new_string = (char*) malloc((strlen(a) + strlen(b) + 1) * sizeof(char));
strcpy(new_string, a);
strcat(new_string, b);
printf("%s", new_string);

Sadly, the only way to do this relies on dynamic memory management or VLA which can be tricky to work with.

  • 2
    "After creating a char* of a certain size" is unclear. All `char *` have the same size. A pointer is not an array an array is not a pointer. Perhaps you mean the array of pointers cannot change its array size? – chux - Reinstate Monica Oct 03 '22 at 00:22
  • "the only way"? Could use variable length arrays (VLA), when supported. – chux - Reinstate Monica Oct 03 '22 at 00:24
  • As, perhaps, the OP meant, the target buffer could be defined (compile time) with a size large enough to accommodate all that will be put into it. Naturally, checking BEFORE overrunning the buffer needs to be a part of any code that writes into it. (The OP code defines an array of pointers, not bytes... I do know...) – Fe2O3 Oct 03 '22 at 01:07