sprintf expects argument of type char * - but type IS char - command

Thats code:
void bleAdvData(char *advData, uint8_t size){
char command[18+size];
uint8_t commandUint[18+size];
sprintf(command, "AT+BLEADVDATA=\"%s\"\r\n", *advData);
Warning in sprintf line:
Argument %s expects argument of type "char *", but argument 3 has type int
Why?
And what i have to do:
I want to trasfer a string(advData) wtich the length of "size" into a function for get a string command like:
AT+BLEADVDATA="advData"\r\n

Your variable advData is defined as char * in the argument list. This is a pointer to an address where character data is stored. However, in your sprintf() you use *advData, ie the actual place where advData points to, not the address itself.
Take the * off in the sprintf(), and all should be fine.

To clarify: char *advData on the first line makes advData a char *.
But then you added an asterisk to advData so you have * (char *advData).
So you want this:
sprintf(command, "AT+BLEADVDATA=\"%s\"\r\n", advData);
That extra asterisk "dereferences" the advData so you're now trying to pass in the first character of the string
sprintf then complains since that's not a valid string. If you ran this it'd either crash or on the ESP32 give you gibberish.
I recommend using the Warnings as Errors option on the ESP32. It's very rare that a warning won't be meaningful, and the ESP32 doesn't crash as easily as a program running on a modern PC OS.
That leads to really hard to find bugs where stuff randomly works or crashes with no clear pattern.

Related

How to get ioctl command value of the given driver?

How to get ioctl command value (integer value) of the given driver, which is not part of kernel source tree.
Example
#define ioctl_cmd _IOW('a', 1, struct example*)
I need an integer value of the command ioctl_cmd without actually modifying the driver.
The _IOW(type,nr,size) macro is defined for userspace code by #include <linux/ioctl.h>. The actual source of the macro is in "/usr/include/asm-generic/ioctl.h".
One way to get the integer value of the ioctl command value is to print it to the terminal in a C program:
#include <stdio.h>
#include <linux/ioctl.h>
#include "your_driver_ioctls.h" // defines `ioctl_cmd`
int main(void)
{
printf("ioctl_cmd = %u (0x%x)\n", ioctl_cmd, ioctl_cmd);
}
Alternatively, you can look at the definition of _IOW in the source to see how the ioctl command code is composed:
Bits 31 to 30 indicate the direction of transfer of the memory pointed to by the optional third argument of the ioctl() call:
_IOC_NONE = 0 (no direction)
_IOC_WRITE = 1 (userland is writing to kernel)
_IOC_READ = 2 (userland is reading from kernel)
_IOC_WRITE | _IOC_READ = 3 (userland is writing to and reading from kernel)
The _IOW(type,nr,size) macro sets the direction to _IOC_WRITE.
Bits 29 to 16 indicate the 14-bit size of the memory pointed to by the optional third argument of the ioctl() call. The _IOW(type,nr,size) macro sets this to the size of the type specified in the third parameter of the macro call (sizeof(size)).
Bits 15 to 8 indicate the 8-bit "type number" of the ioctl command code. Historically, a single ASCII character value was used for the type number, but any unsigned number up to 255 can actually be used. All the ioctl command codes defined for a device generally use the same type number. The _IOW(type,nr,size) macro sets this to the first parameter of the macro call (type).
Bits 7 to 0 indicate the 8-bit "function number" of the ioctl command code. The _IOW(type,nr,size) macro sets this to the second parameter of the macro call (nr).
Note that the above way of defining ioctl command codes is mostly just a convention. In particular, earlier subsystems such as TTY use a simpler scheme consisting of just a "type number" and a "function number").
Your #define ioctl_cmd _IOW('a', 1, struct example*) is unusual because it says that the optional third argument of the ioctl() call points to a struct example* and the size of that would be 4 or 8 (depending on the size of pointers in userspace). More conventionally, it would be defined as _IOW('a', 1, struct example).

char array in c in overflowed scanf operation

I am new to C programming and i am really confused on below code:
#include <stdio.h>
#include <string.h>
int main(void)
{
char arrstr[6];
int i;
printf("Enter: ");
scanf("%s",arrstr);
printf("arrstr is %s\n",arrstr);
printf("length os arrstr is %d\n",strlen(arrstr));
for(i=0;i<20;i++)
{
printf("arrstr[%d] is %c, dec value is %d\n",i,arrstr[i],arrstr[i]);
}
return 0;
}
As from my understanding, after the declaration of arrstr[6], the compiler will allocate 6 bytes for this char array, and consider the last '\0' char, 5 valid chars can be stored in the char array.
But after i run this short code, i get below result:
The printf shows all chars i input, no matter how long is it. But when i using an index to check the array, seems i cannot find the extra chars in the array.
Can anyone helps to explain what happened?
Thanks.
Try changing your code by adding this line right after the scanf statement:
arrstr[5] = '\0';
What has happened is that the null character was overwritten by the user entry. Putting the null character back in manually gives you proper behavior for the next two lines, the printf statements.
The for loop is another matter. C does not have any kind of bounds checking so it's up to the programmer to not overrun the bounds of an array. The values you get after that could be anything at all, as you are just reading uninitialized RAM bytes at that point. A standard way of avoiding this is to use a const int variable to declare the array size:
const int SIZE = 6;
char arrstring[SIZE];
Then also use SIZE as the limit in the for loop.
P.S. There is still a problem here with the user entry as written, because a user could theoretically enter hundreds of characters, and that would get written out-of-bounds it seems, possibly causing weird bugs. There are ways to limit the amount of user entry, but it gets fairly involved, here are some stackoverflow posts on the topic. Keep in mind for future reference:
Limiting user entry with fgets instead of scanf
Cleaning up the stdin stream after using fgets

What's the proper way to initialize an unsigned integer to 0xFFFFFFFF in Powershell?

My CRC calculation algorithm requires that I initialize a 32-bit unsigned integer variable to 0xFFFFFFFF (all 1's in binary so that I can use the variable as a bitmask). If I just write [uint32]$r=0xFFFFFFFF, I get the following error message:
Cannot convert value "-1" to type "System.UInt32". Error: "Value was either too large or too small for a UInt32."
The syntax I'm currently using is [uint32]$r="0xFFFFFFFF", but it seems a bit over the top with the string to integer conversion (I'm coming from the C/C++ programming world). I'm pretty new to Powershell, so I was wondering if Powershell has a more efficient/straightforward way of initializing a variable like this.
How about [UInt32]::MaxValue.
The value of this constant is 4,294,967,295; that is, hexadecimal 0xFFFFFFFF.
PowerShell doesn't have any syntax for UInt32 literals, but you could cast an Int64 literal to [uint32] with the l type postfix:
[uint32]0xFFFFFFFFl

why printf('c') cause Segmentation fault?

This is my test code.
#include <stdio.h>
int main() {
printf('c');
return 0;
}
SO: ubuntu16.04
Compiler version: gcc5.3
Running the code above cause Segmentation fault error in "movdqu (%rdi),%xmm0 ".
I had google it, but I want to know why cause Segmentation fault
Because you are trying to pring a char, not a string. First argument of printf() function is a format string.
Strings are quoted in "", chars in ''.
I fond the error when use GDB debug the program.
image
SHORT:
This is prototype of printf function in C:
int printf ( const char * format, ... );
You should pass c-string (like "this is my message") instead of char.
DETAILED:
This is prototype of printf function in C:
int printf ( const char * format, ... );
This means that the first argument should be a pointer to a null-terminated array of char. In fact, printf reads value of first argument which is address of an c-string in memory, then go to that address and reads bytes by bytes to reach null character. In two condition this code causes segmentation fault:
The address is pointed by the first argument of printf is outbound of memory address of your program.
printf can't find any null characters beginning from the specified address before reaching end of memory boundary of your program.
Please be careful about using non-pointer variables in place of pointers. This cause your program to crash without a argumentive reason.

Variadic macros with 0 arguments in C99

I have some debugging code that looks like the following:
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define AT __FILE__ ":" TOSTRING(__LINE__)
void __my_error(const char*loc, const char *fmt, ...);
#define my_error(fmt, ...) __my_error(AT, fmt, ##__VA_ARGS__)
The last macro is used so I can insert the location into the debug output as to where the error occurred. However, when I call the function like this:
my_error("Uh oh!");
I would like my code to be C99, so I find when this compiles, I get the following error:
error: ISO C99 requires rest arguments to be used
I know I can solve this by changing the call to
my_error("Uh oh!", NULL);
But is there any way to make this look less ugly? Thanks!
I see two solutions to this problem. (Three if you count 'stick with gcc').
Extra special case macro
Add a new macro for when you want to print a fixed string.
#define my_errorf(str) my_error(str, NULL)
Pro: Minimum amount of extra code.
Con: It's easy to use the wrong macro (but at least you notice this at compile time).
Put fmt inside the '...'
Vararg macro's can have only __VA_ARGS__ as parameter (unlike vararg functions). So you can put the fmt argument inside the __VA_ARGS__ and change your function.
void __my_error(const char *loc, ...);
#define my_error(...) __my_error(AT, __VA_ARGS__)
Pro: One syntax/macro for all error messages.
Con: Requires rewriting of your __my_error function, which might not be possible.