man ascii

image.png
image.png

ASCII and ctype

  1. int isxdigit(int c)
  2. {
  3. return isdigit(c) || ((unsigned)c|32)-'a' < 6;
  4. }

image.png
|32保证了可以检测到A等大写字母,因为ASCII码为65,aASCII码为97,如果或上32,就相当于补上了他们的差值32。

strcpy and strncpy

  1. char *strcpy(char *dst, const char *src)
  2. {
  3. char *result = dst;
  4. while ((*dst++ = *src++)) ;
  5. return result;
  6. }
  7. // taken from the strncpy man page
  8. char *strncpy(char *dest, const char *src, size_t n)
  9. {
  10. size_t i;
  11. for (i = 0; i < n && src[i] != '\0'; i++)
  12. dest[i] = src[i];
  13. for ( ; i < n; i++)
  14. dest[i] = '\0';
  15. return dest;
  16. }

Aside: In the days of yore, pointer arithmetic had a performance advantage over array indexing, but smart modern compilers make this largely moot. A lot of old code and old programmers haven’t yet gotten that memo. Pointer arithmetic is especially rife in code that wrangles C-strings where it is perhaps tolerable, but for arrays of type other than char, array indexing is almost always going to be more readable.

gdb x command

(gdb) x/8bc buf
image.pngbuf是main中的一个变量。

Using Valgrind

image.png
backtrace
image.png

myprintenv

echo $USER $HOST $HOME $SHELL
image.png
printenv, 打印环境变量。env,修改环境变量
image.png
c编程获取并打印环境变量

  1. /*
  2. * File: myprintenv.c
  3. * ------------------
  4. * Read lab2 writeup for more information.
  5. */
  6. #include <stdio.h>
  7. #include <string.h>
  8. const char *get_env_value(const char *envp[], const char *varname)
  9. {
  10. for (int i = 0; envp[i] != NULL; i++){
  11. //printf("%s\n", envp[i]);
  12. char *result = strstr(envp[i], varname);
  13. if (result == envp[i]){
  14. //if result is null, don't do anything
  15. //envp[i] can be null but will be blocked by for
  16. result += strlen(varname);
  17. if (*result == '=')
  18. return ++result;
  19. }
  20. }
  21. return NULL; // TODO
  22. }
  23. /* Function: main
  24. * --------------
  25. * Ordinarily main() has just two arguments (argc/argv); this alternate
  26. * prototype includes an optional third argument which is an array of
  27. * environment variables (like argc/argv, the values passed to this third
  28. * arg are set automatically by the operating system when the program is
  29. * launched). Programs can use either form for main. The 2-argument
  30. * version is more common, but this program will use the main with
  31. * 3rd argument to get access to the environment variables.
  32. * (In fact, many programmers don't even know about this optional 3rd
  33. * argument, so now you're already elite! :-) )
  34. *
  35. * Each array entry in this third argument is a string (pointer char*),
  36. * where the string pointed to is of the form "NAME=value", for different
  37. * environment variable NAMEs and configuration values. The array's last
  38. * entry is a NULL pointer, which acts as a sentinel to identify the
  39. * end of the array (which is why we can get away with not including an
  40. * accompanying array size argument, as we would normally do when passing
  41. * arrays in C).
  42. */
  43. int main(int argc, char *argv[], const char *envp[])
  44. {
  45. if (argc == 1) {
  46. for (int i = 0; envp[i] != NULL; i++)
  47. printf("%s\n", envp[i]);
  48. } else {
  49. for (int i = 1; i < argc; i++) {
  50. const char *value = get_env_value(envp, argv[i]);
  51. if (value != NULL) // if not found, don't print anything
  52. printf("%s\n", value);
  53. }
  54. }
  55. return 0;
  56. }

代码逻辑非常棒。