2

A program to swap values:

#include <stdio.h>
#include <conio.h>

void swap(int *a, int *b);

void main()
{
    int a, b;
    printf("Enter two numbers: ");
    scanf_s("%d%d", &a, &b);

    printf("Before swap\n");
    printf("a = %d, b =  %d\n", a, b);
    swap(&a, &b);
    printf("After swap\n");
    printf("a = %d, b = %d", a, b);
}

void swap(int *a, int *b)
{
    printf("Enter the swapped numbers: \n");
    scanf("%d%d", a, b);
}

ERROR

why should I use scanf_s here instead of scanf? Why does this happen?

Thank you for your help.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
J P
  • 21
  • 3
  • 4
    You can safely ignore that warning. `scanf` has plenty of problems, but on balance, `scanf_s` is no better. – Steve Summit Nov 28 '21 at 14:03
  • 2
    You shouldn't use `scanf_s()`. [**Field Experience With Annex K — Bounds Checking Interfaces**](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm): "A widespread fallacy originated by Microsoft's deprecation of the standard functions in an effort to increase the adoption of the APIs is that every call to the standard functions is necessarily unsafe and should be replaced by one to the "safer" API ... Microsoft Visual Studio implements an early version of the APIs. However, the implementation is incomplete and conforms neither to C11 nor to the original TR 24731-1. ..." – Andrew Henle Nov 28 '21 at 15:10
  • 2
    (cont) "... As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable." – Andrew Henle Nov 28 '21 at 15:11

2 Answers2

1

With scanf you can scan a string :

char buffer[256];
scanf("%s", buffer);

But it can lead to a buffer overflow if the input string is larger than the destination buffer : like strcpy it will copy until it finds a '\0' inside the input. So your compiler is telling you to use scanf_s instead to specify the size of your buffer so it won't write past it :

char buffer[256];
scanf_s("%s", buffer, 256);

But in your case you are just inputing single ints you can use scanf anyway. scanf_s is not a standard function so be careful if your code has to be compile outside visual studio.

More here : Difference between scanf and scanf_s

Scouarn.
  • 175
  • 8
  • 1
    `scanf( "%255s", buffer );` Done. `scanf_s()` doesn't improve security and safety, but does make your code non-portable. – Andrew Henle Nov 28 '21 at 15:08
  • I'll remember to print a paper copy of the scanf man page. ;) – Scouarn. Nov 28 '21 at 15:44
  • 1
    The Microsoft version specifies `scanf_s("%s", buffer, 256U)` whereas the C Standard version assumes `scanf_s("%s", buffer, sizeof buffer)`. The size argument has type `UINT` on one side and `size_t` on the other, which were identical on 32-bit targets, but have a different size on 64-bit targets. The simple solution to prevent buffer overflow has always been `scanf("%255s", buffer)` and that's what the warning should say. It is sad that `*` has a different meaning for `scanf` and `printf` but history cannot be rewritten. – chqrlie Nov 28 '21 at 16:16
1

In the posted code there is no reason to use scanf nor scanf_s in the swap function.

scanf_s is a function introduced by Microsoft as a supposedly safer(1) alternative to scanf that is too often used carelessly by unsuspecting programmers, especially for %s, %[ and %c conversions, leading to security flaws.

scanf_s was standardized as an optional extension with subtly different semantics. Programs using scanf_s are thus not portable.

Microsoft modified their C toolchain to push programmers to use scanf_s, issuing warnings or errors whenever they encounter scanf references. This is the cause for the message shown in the screenshot.

In your program, scanf_s and scanf would behave essentially the same way as the conversion %d%d has the same semantics for both functions, yet scanf_s would detect and handle null pointer arguments for %d (causing the program to exit) whereas scanf would just have undefined behavior (causing the program to exit with a segmentation fault).

The swap function can be written this way:

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

Note also that main should have an int return type.


(1) This subject is quite sensitive as commented by Andrew Henley: scanf_s is a function introduced by Microsoft as a vendor-specific, non-portable, not-any-safer alternative to scanf that results in vendor-lock-in for your code base. An illustration of their internal EEE strategy.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 2
    "`scanf_s` is a function introduced by Microsoft as a **vendor-specific, non-portable, not-any-safer** alternative to `scanf` **that results in vendor-lock-in for your code base**" [FTFY](https://en.wikipedia.org/wiki/Embrace,_extend,_and_extinguish) ;-) – Andrew Henle Nov 28 '21 at 14:59
  • I think the swap thing was just an example, you wouldn't make a swap function that asks the users to swap the values themselves if not on purpose. x) – Scouarn. Nov 28 '21 at 15:35
  • @AndrewHenle: Agreed. Answer updated :) – chqrlie Nov 28 '21 at 15:46