IT graph

気になったデバイスやプログラムで楽しくやっていけたら良いなと思っております。

C言語 ポインターについて

ポインターについて
ポインタ変数と通常の変数を宣言し、ポインタ変数に通常変数のアドレスを代入してみる
ポインタ変数は、アドレスの値渡しを受け取る役目として使われる。

    int *p ;    //ポインタ変数
    int i = 2;

    printf("p: %p\n", p);
    printf("&i: %p\n", &i);

    p = &i;    //&をつけることで、アドレスを求めることができる
    printf("p: %p\n", p);
    printf("&i: %p\n", &i);
    printf("*p: %d\n", *p); 
    printf("i: %d\n", i);

    i = 3;      //i=3に変更し変数モード(*p)を使って同じことをやってみる
    *p = i;
    printf("%s\n","i=3");
    printf("p: %p\n", p);
    printf("&i: %p\n", &i);
    printf("*p: %d\n", *p); 
    printf("i: %d\n", i);
    


以下のように値が同じになる

p: (nil)
&i: 0x7ffd07670ac4

p: 0x7ffd07670ac4
&i: 0x7ffd07670ac4
*p: 2
i: 2

p: 0x7ffd07670ac4
&i: 0x7ffd07670ac4
*p: 3
i: 3

配列について
配列を宣言し、アドレスを確認する

    char str[2]="ab";
    printf("str[0]: %c\n", str[0]); //1文字出力
    printf("str[1]: %c\n", str[1]);
    printf("str[2]: %c\n", str[2]); //文字列として出力
    printf("str: %p\n", str);       //アドレスが出力される

配列については&演算子を使わなくてもアドレスを出力することができる
str[0]は配列の0番目のアドレス、strは配列全体における先頭要素のアドレスを表すため
結果的に同じ値になる。

str[0]: a
str[1]: b
str[2]: 
str: ab
str: 0x7ffdc0394dd2

ポインタ配列について
ポインタ変数を加減算することで、ポインタ変数が指す型のサイズだけアドレスが加減算される。

Linux group / id / accesslist

■グループの追加・削除・変更
groupadd
groupdel
groupmod

■ユーザーの追加・削除・変更
useradd
  groupも同じ名前になる
userdel
usermod

■パスワードの設定
passwd
gpasswd

■ユーザーをグループに追加・削除
usermod -aG
gpasswd -a/-d/-M

■設定・データベースの確認
getent
  $ getent passwd
  $ getent group

id
groups

■アクセス制御リスト
 getfacl
 setfacl -m g:グループ名:rwx ディレクトリ名
  読み取りの場合でも実行権限が必要っぽい
 setfacl -m d:g:グループ名:rwx ディレクトリ名
 配下の階層でmkdirを行った場合に、アクセス制御リストが引き継がれる。
  上の設定と両方必要。

■アクセス権限設定
 chmod 2XXX
  ディレクトリのオーナーグループとしてファイルを編集する
   既に存在するファイルの場合は、オーナーもオーナーグループも変更しない
   新しくファイルを作成する場合は、オーナーは自分でオーナーグループはディレクトリのオーナーグループと同じ

  

C言語の文字列について(ポインタ演算、NULL、初期化など)

char変数について
以下のように5文字サイズのchar型変数に6文字を入れた場合

char str2[5] = "test23";
import numpy as np
arr = np.array([1, 2, 3])

以下のようにコンパイル時に警告がでる

hello.c:5:16: 警告: initializer-string for array of ‘char’ is too long
    5 | char str2[5] = "test23";
      |                ^~~~~~~~

以下のように5文字分のサイズに5文字を入れた場合

char str2[5] = "test2";

エラーにならず正常に稼働するがNULLは入らない(out2-5は次のアドレス)

out2-0:t
out2-1:e
out2-2:s
out2-3:t
out2-4:2
out2-5:

16進数表記(utf8)で出力する(printfでフォーマット指定子を%x)

out2-0:74
out2-1:65
out2-2:73
out2-3:74
out2-4:32
out2-5:0

■iint型の配列

int iarray5[5] = {11111, 222222, 3333333, 44444444};
printf("iarray5[0]: %d\n", iarray5[0]);
printf("iarray5[1]: %d\n", iarray5[1]);
printf("iarray5[2]: %d\n", iarray5[2]);
printf("iarray5[3]: %d\n", iarray5[3]);
printf("iarray5[4]: %d\n", iarray5[4]);
printf("iarray5: %p\n", &iarray5);
iarray5[0]: 11111
iarray5[1]: 222222
iarray5[2]: 3333333
iarray5[3]: 44444444
iarray5[4]: 0
iarray5: 0x7fff2e8eaee0

■charの配列(配列の配列)
以下は要素数6の配列を5つの要素で定義

 char array5[5][6] = {"test1", "test2", "test3", "test4"};
    printf("array5[0]: %s\n", array5[0]);
    printf("array5[1]: %s\n", array5[1]);
    printf("array5[2]: %s\n", array5[2]);
    printf("array5[3]: %s\n", array5[3]);
    printf("array5[4]: %s\n", array5[4]);

内容を確認

array5[0]: test1
array5[1]: test2
array5[2]: test3
array5[3]: test4
array5[4]: 

■iint型の配列の関数渡し
以下のどの方法でも同じ結果になるが2番目が一般的らしい

    //数字の配列
    int iarray5[5] = {11111, 222222, 3333333, 44444444};
    int numlen = sizeof(iarray5) / sizeof(int);
    ret = psetMsg(iarray5, numlen);
    ret = isetMsg(iarray5, numlen);
    ret = asetMsg(iarray5, numlen);

//関数部分
int psetMsg(int *pint, int numlen){
    printf("pint address: %p\n", pint);
    printf("*pint: %d\n", *pint);
    printf("numlen: %d\n", numlen);
    return 0;
}
int isetMsg(int pint[], int numlen){
    printf("pint address: %p\n", pint);
    printf("*pint: %d\n", pint[0]);
    printf("numlen: %d\n", numlen);
    return 0;
}int asetMsg(int aint[5], int numlen){
    printf("pint[6] address: %p\n", aint);
    printf("*pint[6]: %d\n", aint[0]);
    printf("numlen: %d\n", numlen);

    return 0;
}

内容を確認

pint address: 0x7ffe2ad1bd40
*pint: 11111
numlen: 5
pint address: 0x7ffe2ad1bd40
*pint: 11111
numlen: 5
pint[6] address: 0x7ffe2ad1bd40
*pint[6]: 11111
numlen: 5

■ポインタ演算
以下のポインタを渡す関数部分を変更

//関数部分
int psetMsg(int *pint, int numlen){
    int *plint;
    printf("pint address: %p\n", pint);
    printf("*pint: %d\n", *pint);
    printf("*(pint + 1): %d\n", *(pint + 1));
    printf("*(pint + 2): %d\n", *(pint + 2));
    printf("pint[1]: %d\n", pint[1]);
    printf("pint[2]: %d\n", pint[2]);
    printf("*pint: %d\n", *pint);
    *plint++ += *pint++;
    printf("*pint: %d\n", *pint);
    printf("*plint++: %d\n", *plint);
    printf("*pint++: %d\n", *pint++);
    *pint = *pint++;
    printf("*pint++: %d\n", *pint++);
    printf("numlen: %d\n", numlen);
    return 0;
}

内容を確認

pint address: 0x7ffd88dee440
*pint: 11111
*(pint + 1): 222222
*(pint + 2): 3333333
pint[1]: 222222
pint[2]: 3333333
*pint: 11111
*pint: 222222
*plint++: 222222
*pint++: 222222
*pint++: 3333333
numlen: 5

文字列操作

■文字列の格納
リテラルによる初期化はOK

char str1[] = "test";

配列による初期化はNG

char str1[] = "test";
char str2[] = str1;

分割して格納する方法

char str3[5] = {"t", "e", "s", "t","\0"}; //最期にNULLをいれる

以下はポインタ変数(アドレスを代入する変数)への格納となってしまうのでNG

 str1= "test";

以下はポインタ変数同士の比較となってしまうので常に異なる

 if ( str1 == str2 ) {
 }

初期化以外で配列へまとまった値を入れたい場合は関数を使う
文字列型のデータのコピーは数値型のデータのように「=」記号を使って代入コピーしようとしても、意図通りにならない。
strcpyはコピー元の`\0`までコピーする

 strcpy(str6, str2) //コピー先、コピー元の順


NULL, \0, 0について
■NULL
ヌルポインタを意味する。で次のように定義されている。

#define NULL ((void *)0)

■\0(ヌル文字)
(char)0と同じ
■0
(int)0として扱う

結局、(char)0も(int)0もC言語(環境UTF-8)上では文字コードは0x00で同じなため、違いはない。
※C++だと変わってくる?<<初期化について(memset)>>
void *memset(void *buf, int ch, size_t n);

第一引数はメモリのポインタ
第二引数はセットする値
第三引数はセットするサイズ

例 memset(tmp, '\0', sizeof(tmp));

clang prinft

printf 標準出力を使う printf(出力文字フォーマット, 出力する変数や値)
sprintf メモリを使う sprinf(出力先アドレス, 出力文字フォーマット, 出力する変数や値)
fprintf ファイルを使う fprintf(出力先ファイル,出力文字フォーマット, 出力する変数や値)
 fprintfの出力先にstdoutを指定すれば標準出力へ出力される

変数tmpのサイズ分だけtmpへnullセット
memset(tmp, '\0', sizeof(tmp));



主なフォーマット指定子

%d : 整数
%f : 浮動小数点数
%c : 単一の文字
%s : 文字列
%p : ポインターを出力

red hat epel install

[root@localhost ~]# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y
サブスクリプション管理リポジトリーを更新しています。
メタデータの期限切れの最終確認: 0:27:40 前の 2024年03月17日 13時15分22秒 に実施しました。
epel-release-latest-9.noarch.rpm 18 kB/s | 19 kB 00:01
依存関係が解決しました。
==============================================================================================================================
パッケージ アーキテクチャー バージョン リポジトリー サイズ
==============================================================================================================================
インストール:
epel-release noarch 9-7.el9 @commandline 19 k

トランザクションの概要
==============================================================================================================================
インストール 1 パッケージ

合計サイズ: 19 k
インストール後のサイズ: 26 k
パッケージのダウンロード:
トランザクションの確認を実行中
トランザクションの確認に成功しました。
トランザクションのテストを実行中
トランザクションのテストに成功しました。
トランザクションを実行中
準備 : 1/1
インストール中 : epel-release-9-7.el9.noarch 1/1
scriptletの実行中: epel-release-9-7.el9.noarch 1/1
Many EPEL packages require the CodeReady Builder (CRB) repository.
It is recommended that you run /usr/bin/crb enable to enable the CRB repository.

検証 : epel-release-9-7.el9.noarch 1/1
インストール済みの製品が更新されています。

インストール済み:
epel-release-9-7.el9.noarch

完了しました!
[root@localhost ~]#

linux tips

#findで探したものを移動
find ./ -maxdepth 1 -name "*test*" -mtime 1 -emtpy -type f \ xargs -I% mv % ./test

#findで探したものを削除
find ./ -maxdepth 1 -name "*test*" -mtime 1 -emtpy -type f -delete

#マッチしないものを出力
grep -Fxv -f text2.txt text1.txt

#変数fに付与される./を削除
res=`echo $f | sed "s/.\///g"`

#拾ったファイル名に対しlsの結果をテキストに保存
res2=`ls -l ${res} > ./cmd/$f.res 2>&1`

#プロセス結果をREADし、変数fにいれる
while read -r f; do
xxxxxx
done < <(find ./ -mindepth 1 -maxdepth 1)
#done < <(ls ./)
#done < <(cat ./conf/conf.txt)

#変数fのデリミタ半角スペースで1つめのフィールドを取得
res=`echo $f | cut -f 1 -d " "`

#ポート番号とサービスを調べる
ss -ltpu

#Linuxカーネルの確認方法
uname -a

#Linux OS(ディストリビューション)の確認方法
cat /etc/os-release