Why do i gett warnings by using strcpy_s and strcat_s? - c

I programmed an example on my Win64 PC with code:blocks using strcpy_s and strcat_s. The program works, but I get the warning messages "warning: implicit declaration of function 'strcpy_s' for strc_s and strcat_s respectively. The compiler settings have C11 enabled. And why can't I find the two functions in string.h?
// This program uses strcpy_s and strcat_s to build a phrase.
#include <string.h> // for strcpy_s, strcat_s
#include <stdio.h> // for printf
int main(void)
{
char stringBuffer[80];
strcpy_s(stringBuffer, sizeof(stringBuffer), "Hello world from ");
strcat_s(stringBuffer, sizeof(stringBuffer), "strcpy_s ");
strcat_s(stringBuffer, sizeof(stringBuffer), "and ");
strcat_s(stringBuffer, sizeof(stringBuffer), "strcat_s!");
printf("stringBuffer = %s\n", stringBuffer);
}

From cppreference:
As with all bounds-checked functions, strcpy_s only guaranteed to be
available if __STDC_LIB_EXT1__ is defined by the implementation and if
the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1
before including <string.h>.
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
See also: __STDC_LIB_EXT1__ availability in gcc and clang

As near substitutes for the strcpy() and strcat() methods, the strcpy s() and strcat s() functions are described in ISO/IEC WDTR 24731. (). The maximum length of the destination buffer is specified by an additional rsize t type argument that is required by these procedures.
When there are no breaches of the constraints, the strcpy s() function is equivalent to strcpy(). The strcpy s() function duplicates characters from a source string—up to and including the terminating null character—to a destination character array. If the function is successful, it returns 0.
Only when the source string can be completely copied to the destination without filling the destination buffer does the strcpy s() function succeed. if the maximum size of the destination buffer is equal to zero, more than RSIZE MAX, or smaller, or if either the source or destination pointers are NULL

Related

Unhandled exception at 0x00007FFB158DA726 (ucrtbase.dll) in AI.exe: 0xC0000005: Access violation writing location 0x00007FF76DE322E0

When I run the code here happen after
scanf("%[^\n]", order);
Full code:
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE
#include <stdio.h>
#include <Windows.h>
#include "Colors.h"
#include <string>
#include "Functions.h"
#include <stdbool.h>
using namespace std;
int main() {
//vars
char* order = "";
int WinH;
int WinW;
bool error = false;
GetDesktopResolution(WinH, WinW);
// end vars
//funcs
//DelayedStart();
//end funcs
Sleep(1500);
system("CLS");
Sleep(250);
SetConsoleTitle(L"AI APP - Main");
printf("Hello,\nHow can I help you\n>>");
F_GREEN;
scanf("%[^\n]", order); //error here
F_B_Defalt;
if (order == "open youtube") {
ShellExecute(0, 0, L"http://www.youtube.com", 0, 0, SW_SHOW);
}
else
{
printf("%s\n", order);
puts("Whoops");
}
system("PAUSE");
}
Visual Studio 2022 V17.4
You are scanning into a string literal(""), which provokes undefined behaviour!
Actually you should have gotten a compiler warning, because of assigning this string literal, which has type char const/*!!!*/ *, to a variable of char /*non-const!*/ *. Some compilers do allow this for reasons of compatibility to C. Some of these (e.g. GCC) allow to enhance this warning to a compilation error, not sure if MSVC does so, too, but if it does, you should do so!
Additionally this string literal only contains room for one single character, so (if it was possible at all...) you only could read an empty string into (containing the terminating null character), otherwise you'll provoke undefined behaviour again for writing beyond array bounds.
Either of these two kinds of undefined behaviour might have provoked the segmentation fault.
To fix provide a writable character buffer long enough to hold expected input:
char order[128];
// ...
scanf("%127[^\n]", order);
Note how in above format string a maximum length for reading characters is specified, this needs to be, though, one less than the buffer size as the scan operation will yet append the terminating null character.
Note, too, how order decays to a pointer to its first element implicitly, so you do not need to take the address of – actually this would even be wrong and provoke undefined behaviour for providing non-matching pointer types (char(*)[128] vs. char*) to the format specifier (even though the address would be the same).

How to use formatting strings in user-defined functions?

I want to write a function to print characters on an LCD in a similar way that printf/sprintf does using formatting strings.
You may use sprintf function to format the strings and print to LCD.
char buffer[50];
int a = 10, b = 20, c;
c = a + b;
sprintf(buffer, "Sum of %d and %d is %d", a, b, c);
Now the buffer will have the formatted strings
You could write a variadic function and pass the parameters on to vsnprintf():
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void display(int foo, int bar, char const *format, ...)
{
va_list arglist;
va_start(arglist, format);
int length = vsnprintf(NULL, 0, format, arglist);
char *buffer = malloc(length * sizeof *buffer);
vsnprintf(buffer, length, format, arglist);
va_end(arglist);
puts(buffer);
free(buffer);
}
int main(void)
{
display(42, 13, "%s %d %f", "Hello", 99, 100.13);
}
This answer takes the best parts of all of the other answers and puts them into one. I consider it to be the best way to do this given all factors, and will explain in more detail after presenting the example.
Summary:
Here's a full example, including with basic error checking in the function. Here I create a printf-like function called lcd_printf(), which works exactly like printf(). It uses vsnprintf() to store a formatted string into a statically-allocated buffer. You can then send this buffer to the LCD display at the location indicated by my comment.
Example Code:
lcd_print.h:
// For info on the gcc "format" attribute, read here under the section titled
// "format (archetype, string-index, first-to-check)":
// https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes.
int lcd_printf(const char * format, ...) __attribute__((format(printf, 1, 2)));
lcd_print.c:
#include "lcd_print.h"
#include <stdarg.h> // for variable args: va_list
#include <stdio.h> // for vsnprintf()
#include <limits.h> // for INT_MIN
// `printf`-like function to print to the LCD display.
// Returns the number of chars printed, or a negative number in the event of an error.
// Error Return codes:
// 1. INT_MIN if vsnprintf encoding error, OR
// 2. negative of the number of chars it *would have printed* had the buffer been large enough (ie: buffer would
// have needed to be the absolute value of this size + 1 for null terminator)
int lcd_printf(const char * format, ...)
{
int return_code;
// Formatted string buffer: make as long as you need it to be to hold the longest string you'd ever want
// to print + null terminator
char formatted_str[128];
va_list arglist;
va_start(arglist, format);
// Produce the formatted string; see vsnprintf documentation: http://www.cplusplus.com/reference/cstdio/vsnprintf/
int num_chars_to_print = vsnprintf(formatted_str, sizeof(formatted_str), format, arglist);
va_end(arglist);
if (num_chars_to_print < 0)
{
// Encoding error
return_code = INT_MIN;
return return_code; // exit early
}
else if (num_chars_to_print >= sizeof(formatted_str))
{
// formatted_str buffer not long enough
return_code = -num_chars_to_print;
// Do NOT return here; rather, continue and print what we can
}
else
{
// No error
return_code = num_chars_to_print;
}
// Now do whatever is required to send the formatted_str buffer to the LCD display here.
return return_code;
}
main.c:
#include "lcd_print.h"
int main(void)
{
int num1 = 7;
int num2 = -1000;
unsigned int num3 = 0x812A;
lcd_printf("my 3 numbers are %i, %i, 0x%4X\n", num1, num2, num3);
return 0;
}
Explanation & comparison to alternate approaches:
#Harikrishnan points out you should use sprintf(). This is on the right track, and is a valid, but less versatile and complete approach. Creating a new variadic function which uses vsnprintf(), as #Swordfish and I have done, is better.
#Swordfish does a fantastic demonstration of the proper usage of vsnprintf() in order to create your own printf()-like variadic function. His example (aside from lacking error handling) is the perfect template for a custom printf()-like implementation which relies on dynamic memory allocation. His first call to vsnprintf(), with a NULL destination buffer, does nothing more than determine how many bytes he needs to allocate for the formatted string (this is an ingenious and commonly-used trick for this application), and his second call to vsnprintf() actually creates the formatted string. For non-real-time applications which also have large amounts of RAM (ex: PC applications) this is the perfect approach. However, for microcontrollers I strongly recommend against it because:
It is non-deterministic. Calling free() can take different (and indeterminable before-hand) amounts of time to complete each time you call it. This is because the heap memory becomes fragmented over time. This means this approach is not good for real-time systems.
For more information about various heap implementations for malloc() and free(), review the 5 heap implementations, for example, described by FreeRTOS here: https://www.freertos.org/a00111.html. Search this page for "deterministic".
It is unbounded. It will attempt to malloc() ANY amount of memory required for the formatted string. This is bad, as it is more prone to stack-overflow. On safety-critical microcontroller-based systems, stack overflow needs to be strongly guarded against. A preferred approach is to use statically-allocated memory like I have done, with a fixed maximum size.
Additionally, it is lacking the GCC "format" attribute, which is a nice touch (more on this below).
#P__J__ mentions the GCC "format" attribute. My example uses this as well.
If using the GCC compiler, or any other compiler which has something similar, this is highly recommended to add to any custom printf()-like function you make.
The GCC documentation, under the section called format (archetype, string-index, first-to-check), states:
The format attribute specifies that a function takes printf, scanf, strftime or strfmon style arguments that should be type-checked against a format string.
In other words, it provides extra protections and checks to your custom printf()-like function at compile time. This is good.
For our case, simply use printf as the archetype, and a number for the string-index and first-to-check parameters.
The parameter string-index specifies which argument is the format string argument (starting from 1), while first-to-check is the number of the first argument to check against the format string.
Since non-static C++ methods have an implicit this argument, the arguments of such methods should be counted from two, not one, when giving values for string-index and first-to-check.
In other words, here are some valid example usages for this attribute applied to printf()-like function prototypes:
In C:
int lcd_printf(const char * format, ...) __attribute__((format(printf, 1, 2))); // 1 is the format-string index (1-based), and 2 is the variadic argument (`...`) index (1-based)
int lcd_printf(my_type my_var, const char * format, ...) __attribute__((format(printf, 2, 3))); // 2 is the format-string index (1-based), and 3 is the variadic argument (`...`) index (1-based)
int lcd_printf(my_type my_var, my_type my_var2, const char * format, my_type my_var3, ...) __attribute__((format(printf, 3, 5))); // 3 is the format-string index (1-based), and 5 is the variadic argument (`...`) index (1-based)
In C++:
int lcd_printf(const char * format, ...) __attribute__((format(printf, 2, 3))); // 2 is the format-string index (2-based), and 3 is the variadic argument (`...`) index (2-based)
int lcd_printf(my_type my_var, const char * format, ...) __attribute__((format(printf, 3, 4))); // 3 is the format-string index (2-based), and 4 is the variadic argument (`...`) index (2-based)
int lcd_printf(my_type my_var, my_type my_var2, const char * format, my_type my_var3, ...) __attribute__((format(printf, 4, 6))); // 4 is the format-string index (2-based), and 6 is the variadic argument (`...`) index (2-based)
Read more in my other answer here: How should I properly use __attribute__ ((format (printf, x, y))) inside a class method in C++?.
So, putting everything above together, you get the ideal solution for microcontrollers, which I've presented above.
as most commnly used arm compiler is gcc I will only focus on this one. The compiler can check the format & the prameters same as printf does
__attribute__ ((format (printf...
From the gcc documentation
format (archetype, string-index, first-to-check)
The format attribute specifies that a function takes printf, scanf, strftime or strfmon style arguments which should be
type-checked against a format string. For example, the declaration:
extern int
my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));
causes the compiler to check the arguments in calls to my_printf for consistency with the printf style format string argument
my_format.
The parameter archetype determines how the format string is interpreted, and should be printf, scanf, strftime or strfmon. (You
can also use printf, scanf, strftime or strfmon.) The
parameter string-index specifies which argument is the format string
argument (starting from 1), while first-to-check is the number of the
first argument to check against the format string. For functions where
the arguments are not available to be checked (such as vprintf),
specify the third parameter as zero. In this case the compiler only
checks the format string for consistency. For strftime formats, the
third parameter is required to be zero.
In the example above, the format string (my_format) is the second argument of the function my_print, and the arguments to check start
with the third argument, so the correct parameters for the format
attribute are 2 and 3.
The format attribute allows you to identify your own functions which take format strings as arguments, so that GCC can check the
calls to these functions for errors. The compiler always (unless
-ffreestanding is used) checks formats for the standard library functions printf, fprintf, sprintf, scanf, fscanf, sscanf, strftime,
vprintf, vfprintf and vsprintf whenever such warnings are requested
(using -Wformat), so there is no need to modify the header file
stdio.h. In C99 mode, the functions snprintf, vsnprintf, vscanf,
vfscanf and vsscanf are also checked. Except in strictly conforming C
standard modes, the X/Open function strfmon is also checked as are
printf_unlocked and fprintf_unlocked. See Options Controlling C
Dialect. format_arg (string-index)
The format_arg attribute specifies that a function takes a format string for a printf, scanf, strftime or strfmon style function and
modifies it (for example, to translate it into another language), so
the result can be passed to a printf, scanf, strftime or strfmon style
function (with the remaining arguments to the format function the same
as they would have been for the unmodified string). For example, the
declaration:
extern char *
my_dgettext (char *my_domain, const char *my_format)
__attribute__ ((format_arg (2)));
causes the compiler to check the arguments in calls to a printf, scanf, strftime or strfmon type function, whose format string argument
is a call to the my_dgettext function, for consistency with the format
string argument my_format. If the format_arg attribute had not been
specified, all the compiler could tell in such calls to format
functions would be that the format string argument is not constant;
this would generate a warning when -Wformat-nonliteral is used, but
the calls could not be checked without the attribute.

Passing a pointer (string) to a C function

Please read until the end before you say: "Oh no, this question again..."
I am right now seating in a C course and the following example has been provided in course book:
#include <stdio.h>
#include <stdint.h>
void Terminal_PrintData(uint16_t * const Data);
int main(void){
uint16_t StringData[] = "MyData";
Terminal_PrintData(StringData);
}
void Terminal_PrintData(uint16_t * const Data)
{
printf("Value: %s", *Data);
}
When I compile this masterpiece, this is what I get:
F:\AVR Microcontroller>gcc -o test test.c
test.c: In function 'main':
test.c:7:26: error: wide character array initialized from non-wide string
uint16_t StringData[] = "MyData";
My questions are:
Is it correct to declare a string with uint16_t?
What is recommended way to pass a string to a function?
Your immediate questions:
Is it correct to declare a string with uint16_t?
No.
All strings are always char[]. There ar also wide strings (strings of wide characters), which have the type wchar_t[], and are written with an L prefix (e.g. L"hello").
What is recommended way to pass a string to a function?
As a pointer to the first character in the string, so either char * or wchar_t *. The const qualifier makes no sense here; it would mean that the pointer (not the string itself) is constant (see here). I'd recommend writing wchar_t const * or const wchar_t * instead; it has a different meaning (i.e. the string can't be changed), but it's correct and meaningful.
You mention that this code is from a course book. I'm not sure whether you mean that these are lecture notes handed out by your professor, or whether you bought a published book. In either case, if this snippet is representative of the quality of the book/notes, get a refund.
For now, let's make this code work.
There's an error in this code that will cause the program to crash:
printf("... %s ...", ..., *string, ...) when string is a char* is always wrong. Don't dereference that pointer.
If you insist on using "wide" characters (which is questionable), you're going to have to change a few things:
Rather than using char, you need to include <wchar.h> and use wchar_t instead. As far as I know, uint16_t and uint8_t won't work unless you use explicit casting everywhere. That's because char doesn't have 8 bits, but CHAR_BIT bits.
Wide character literals must start with an L prefix.
Rather than using printf, you need to use wprintf.
In the format string, use %ls rather than %s. (Unless you use Microsoft's compiler.)
Finally, some less grave errors:
As noted, T * const arguments are useless. The author probably meant T const * (or equivalently const T *).
You can remove <stdint.h> and <stdio.h>. We're no longer using uint16_t, and <wchar.h> declares some wide character <stdio.h>-like functions.
I end up with the following code:
#include <wchar.h>
void Terminal_PrintData(wchar_t const * Data);
int main(void){
wchar_t StringData[] = L"MyData";
Terminal_PrintData(StringData);
}
void Terminal_PrintData(wchar_t const * Data)
{
wprintf(L"Value: %ls", Data);
}
This compiles and runs as expected with both GCC and Clang on Linux x86-64.
There are two kinds of strings: "non-wide" ones which consist of chars and "wide" ones which consist of wchar_ts and are written as L"" (single wchar_ts can be written as L''). There are functions to convert between them; apart from these, you cannot intermix them.
Depending on the system, a wchar_t can be 16 or 32 bits wide.
You should view your string as an array of characters (in this case, 8-bit characters) so a uint8_t would suffice. What you normally do is pass the beginning of the string (which is the pointer to the array) to your function. To make it safer, you could also pass the length of the string as an argument, but normally your string will end with a delimiter (\0).
when you pass stringData to your function, you're actually saying &stringData[0], literally "the address (&) of the first element ([0]) of the array".

Error: conflicting types for ‘strlen’

I have a program, but I get an error message. Please help me on this.
#include <stdio.h>
#include <string.h>
int print_strlen(char s[]);
main()
{
char s[20];
printf("Enter the string:\n");
scanf("%s\n", s);
}
int print_strlen(char s[])
{
int l;
l = strlen(s);
printf("Length of the string is: %s\n", l);
}
Don't try to prototype strlen yourself. Just include <string.h>, and use the prototype (and function) it already has. Don't try to write a function of your own with the same name (or, at least officially, any other name starting with str).
The conflicting type it's seeing right now is because the standard requires strlen to return a size_t, not an int.
Also note that the function you have named strlen right now is infinitely recursive -- where it (apparently) tries to call the standard strlen, it'll end up calling itself, and since it does that unconditionally, it'll keep recursing forever (or until the system kills it for overflowing the stack, anyway).
strlen is already defined in string.h hence the error. Change your function name to something else.
Call your function something else, there is already a strlen() declared in string.h.
strlen is a standard function declared in <string.h> and you are trying to define it with another prototype (the standard function takes a char const*, not a char*).
What is your error message?
You shouldn't name your function strlen; there is already a strlen function and you know that won't work because you use the real strlen function in your strlen function. Call it something else, like print_strlen. Also, use void instead of int if you're not actually returning anything from print_strlen.
Other problems not directly related include the obvious buffer overflow; what if you entered text more than 20 bytes long?
strlen is a function provided for you in string.h why reinvent the wheel?
#include <stdio.h>
#include <string.h>
main()
{
char s[20];
printf("Enter the string:\n");
scanf("%s\n",s);
printf("Length of the string is: %s\n",strlen(s));
}
would work perfectly fine.

What headers must be included to use wsprintf with MinGW

I seem to be able to compile code that calls wsprintf with the MinGW gcc if I have these includes (in this order):
#include <stdarg.h>
#include <wingdi.h>
#include <winuser.h>
But I feel like there might be some "cleaner" way to do this. Perhaps with only a single header inclusion. I arrived at this list by searching header files for missing symbols and then including headers one-by-one.
Include <Windows.h>
Do you mean swprintf()?
swprintf() is described in the C99 standard. You need <wchar.h>.
If wsprintf does the same as swprintf you may want to consider using a standard function instead.
7.24.2.3 The swprintf function
Synopsis
[#1]
#include <wchar.h>
int swprintf(wchar_t * restrict s,
size_t n,
const wchar_t * restrict format, ...);
Description
[#2] The swprintf function is equivalent to fwprintf, except
that the argument s specifies an array of wide characters
into which the generated output is to be written, rather
than written to a stream. No more than n wide characters
are written, including a terminating null wide character,
which is always added (unless n is zero).
Do you mean the standard function swprintf? In that case you should include wchar.h.

Resources