0

I want to store a value value via scanf() in the function lorem(), and use it in the function ipsum(). I used static int, but it doesn't work.

static int *value;
void lorem(){
  static int *value;
  scanf("%d", value);
}

void ipsum(){
  static int *value;
  printf("%d", value);
}

void main(){
  lorem();
  ipsum();
}

This is my code, but it keeps forgetting the value of value int.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
Jihwan Ahn
  • 51
  • 1
  • 6
  • This is very basic C that can/should be learnt from any C book or tutorial - passing values to and from functions. `lorem` can return a value that is then passed into `ipsum`. Or `lorem` can take a pointer to an integer which it can write directly and that is then passed to `ipsum`. – kaylum Feb 19 '21 at 03:19
  • 1
    you haven't pointed `value` to anywhere – phuclv Feb 19 '21 at 03:24
  • 1
    Despite having the same name, the `value` declared in function `lorem()` is a different object than the one declared in `ipsum()`, and both of them are different from the one declared at file scope. Delete the declarations inside the two functions to make them use the object declared at file scope. – John Bollinger Feb 19 '21 at 03:24

1 Answers1

4

Do this:

#include <stdio.h>

static int value;

void lorem() {
    // Note: `&` here should be read as "address of". This takes the
    // address of `value` and passes it to scanf as type `int*`, or
    // "pointer to int", AKA: "address of this int". `scanf()` then starts  loading the
    // number you type, byte-by-byte, into the memory at this address.
    // Since that's the address for `value`, you end up putting a
    // numerical value into `value.` Again, the address of `value` is also
    // called a "pointer" to `value`, and `&value` is of type `int*` since
    // `value` is of type `int`. And, ironically enough, passing by
    // pointer is commonly called "pass by reference," and is the
    // alternative to "pass by value".
    scanf("%d", &value);
}

void ipsum() {
    printf("%d", value);
}

int main() {
    lorem();
    ipsum();

    return 0; // no error: program finished successfully
}

You have a couple of mistakes.

  1. First off, don't do static int *value;, do static int value;. The int* says to allocate just enough memory for a pointer to an int, which is a number which stores a RAM memory address to an int, but you don't want that, you want enough memory for an actual int.

  2. Second, each time you do static int *value; inside a function, you are telling that function to use this local version of the value variable, instead of the global version, which is NOT what you want.

  3. (A problem by technicality): main() should be int main() not void main(). Add -Wpedantic to your build flags and you'll see a warning otherwise:

    main.c:32:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
    
    1. On this note, also add return 0; to the end of the main() function to indicate it ran with "no error" (0 is used by popular convention to mean "no error" here).
    2. I've documented some of my notes about compiler build flags in my repo here: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world#additional-c-and-c-build-notes-ex-wgcc-or-clang-compilers.

Also:

  1. (Maybe a problem in my example below, but not applicable to your original code): flush stdout by printing a newline char (\n) OR calling fflush(stdout) before calling scanf(). See here (Why does printf not flush after the call unless a newline is in the format string?), and see also the comments below my answer.

With global variable

Run this code live online here: https://onlinegdb.com/HJ3bqfmtD.

Even better: also tell the user what you want by saying Enter an integer and You entered:

#include <stdio.h>

static int value;

void lorem() {
    printf("Enter an integer: ");
    // Ensure the above printf is fully printed BEFORE waiting for 
    // user input. See my references below. Essentially, you may need
    // to **either** have a `\n` at the end of the printf cmd, OR
    // call `fflush(stdout)` like this, to ensure the stdout buffer
    // is fully flushed (printed to screen), before the `scanf()` 
    // call reads in the user's input. 
    fflush(stdout);
    scanf("%d", &value);
}

void ipsum() {
    printf("You entered: %d\n", value);
}

int main() {
    lorem();
    ipsum();

    return 0; // no error: program finished successfully
}

WithOUT global variable

Run this code live online here: https://onlinegdb.com/ge-LVSsx7.

And better still, avoid using global variables for such a simple case. Global variables are useful and good in some cases, but this isn't one of them.

#include <stdio.h>

int lorem() {
    int value;
    printf("Enter an integer: ");
    // Ensure the above printf is fully printed BEFORE waiting for 
    // user input. See my references below. Essentially, you may need
    // to **either** have a `\n` at the end of the printf cmd, OR
    // call `fflush(stdout)` like this, to ensure the stdout buffer
    // is fully flushed (printed to screen), before the `scanf()` 
    // call reads in the user's input. 
    fflush(stdout); 
    scanf("%d", &value);
    return value;
}

void ipsum(int value) {
    printf("You entered: %d\n", value);
}

int main() {
    int val = lorem();
    ipsum(val);

    return 0; // no error: program finished successfully
}

References:

  1. http://www.cplusplus.com/reference/cstdio/scanf/
  2. http://www.cplusplus.com/reference/cstdio/printf/
  3. Why does printf not flush after the call unless a newline is in the format string?
  4. https://www.cplusplus.com/reference/cstdio/fflush/
  5. What should main() return in C and C++?
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
  • 3
    note that `%i` in scanf is different to `%d` (if you don't know what the difference is , you probably wanted `%d`) – M.M Feb 19 '21 at 03:38
  • @M.M, ah! You're right. Fixing it now. I've actually never used `scanf`, ironically enough. Doesn't exist on microcontrollers and tiny embedded systems. – Gabriel Staples Feb 19 '21 at 03:39
  • @NateEldredge, good point. Adding flush command. – Gabriel Staples Feb 19 '21 at 03:50
  • @user3386109: Yep, apparently so. Thanks. – Nate Eldredge Feb 19 '21 at 04:19
  • please don't use cplusplus.com and link to https://en.cppreference.com/w/c instead which is more correct and updated [What's wrong with cplusplus.com?](https://stackoverflow.com/q/6520052/995714) – phuclv Feb 19 '21 at 04:25
  • and `void main()` is absolutely wrong. It's just an extension in many DOS and Windows compilers. The standard only allows it in freestanding environments [What should main() return in C and C++?](https://stackoverflow.com/q/204476/995714) – phuclv Feb 19 '21 at 04:27
  • @phuclv, `void main()` also works fine in gcc. But yes, with `-Wpedantic`, you are right. I fixed it. – Gabriel Staples Feb 19 '21 at 05:01
  • @phuclv, regarding cplusplus.com vs cppreference.com, I'd like to point out: I regularly edit cppreference.com (see [my answer here](https://stackoverflow.com/a/66164132/4561887), but it is _really not good_ in some areas. Ex: what's an iterator? cppreference.com is/was _not good_ in describing this, but cplusplus.com is [_excellent_](https://www.cplusplus.com/reference/iterator/). Up until a few days ago when I edited cppreference.com, good luck figuring out that a dereferenced iterator of `std::unordered_map` is `std::pair`! So, use both websites. They are wikis. We can make them better. – Gabriel Staples Feb 19 '21 at 05:10
  • Also, I'd like to point out just how _nuanced_ C is. Us 5 or so people probably have 40 to 80 years C experience among us, yet we are correcting each other over so many nitpicky details. Think about how a beginner to C feels. Let this remind us where we came from--we were all there once. – Gabriel Staples Feb 19 '21 at 05:17